반응형
Stream api : 캘랙션 요소를 선언적으로 처리할 수 있는 기능을 제공
-> 흐를수 있는 통로 ,하구수로 비유하면 파이프 같은 존재
특징
1. 선언적 함수 프로그램 어떻게(how)가 아닌 무엇을(what)할 것인지 정의
2. 함수형 프로그래밍 : 불변성과 순수 함수를 활용
3. 자연연사 : 최종 연산이 호출 도기 전까지 중간 연산은 실행 되지 않음
4. 병렬 처리 용이
stram파이프 라인 구성
1. 데이터 소스 : 컬랙션, 배열 , I/o
2. 중간 연산 : 스트림을 다른 스트림을 반환(filter, map, flatMap, reverse....)
3. 최종 연산 : 스트림을 소모하여 결과 생성(collect, forEach, reduce)
장점
1. 간결하고 가독성 높은 코드 -> 복잡한 데이터처리를 선언하고 선언적으로 표현
2. 유지보수 향상 : 함수형 프로그래밍 패턴 적용으로 코드 품질 향상
3. 성능 최적화 : 지연 연산 및 병렬 처리를 통합한 성능 개선 가능
4. 함수형 인터페이스 와 람다 표현식: 간결한 코드 작성 가능
5. 데이터 변환과 필터링 용이 : 복잡한 데이터 처리 로직 단순화
주의 사황
1.성탸 변경 자제 : 스트림 연산중 원본 데이터 수정 금지
2. 무한 스트림 처리 :limit,findFirst등으로 재한 필요
3. 디버깅이 어려움 : 함수형 스타일로 인한 디버깅 복잡성
4. 과도한 사용자제 : 간단한 연산에는 기존 방식이 더 효율적일수 있음
예시
List<String> result = names.stream() // 수도꼭지 열기 - 스트림 생성
.filter(s -> s.length() > 3) // 길이가 3보다 큰 요소만 통과하는 필터 설치
.map(String::toUpperCase) // 대문자로 변환하는 변환기 설치
.collect(Collectors.toList()); // 흐른 데이터를 리스트로 수집
### 3.1 필터링 연산
- **filter()**: 조건에 맞는 요소만 선택
```java
Stream<String> filtered = stream.filter(s -> s.startsWith("A"));
```
- **distinct()**: 중복 제거
```java
Stream<String> unique = stream.distinct();
```
- **limit()**: 처음 n개 요소로 제한
```java
Stream<String> limited = stream.limit(5);
```
- **skip()**: 처음 n개 요소를 건너뜀
```java
Stream<String> skipped = stream.skip(3);
```
### 3.2 변환 연산
- **map()**: 각 요소를 다른 형태로 변환
```java
Stream<String> upperCase = stream.map(String::toUpperCase);
```
- **flatMap()**: 각 요소를 스트림으로 변환 후 하나의 스트림으로 평탄화
```java
Stream<String> flatMapped = stream.flatMap(s -> Arrays.stream(s.split("")));
```
- **mapToInt(), mapToLong(), mapToDouble()**: 기본형 특화 스트림으로 변환
```java
IntStream intStream = stream.mapToInt(String::length);
```
map이랑 flatMap 차이점
map: 각요소를 변환한 스트림으로 반환
반환 값: Stream<List<String>>
flatMap: 모든 원소를 하나의 스트림으로 반환
반환 값: Stream<String>
데이터 처리방식
### 3.3 정렬 연산
- **sorted()**: 자연 순서로 정렬
```java
Stream<String> sorted = stream.sorted();
```
- **sorted(Comparator)**: 지정된 비교자로 정렬
```java
Stream<String> sortedByLength = stream.sorted(Comparator.comparing(String::length));
```
### 3.4 탐색 연산
- **peek()**: 요소를 소비하지 않고 특정 작업 수행 (주로 디버깅에 사용)
```java
Stream<String> peeked = stream.peek(System.out::println);
```
---
## 4. 최종 연산 (Terminal Operations)
최종 연산은 스트림 파이프라인을 실행하고 결과를 도출합니다. 최종 연산이 호출되면 스트림은 소비되어 더 이상 사용할 수 없습니다.
### 4.1 요소 검색
- **findFirst()**: 첫 번째 요소 반환
```java
Optional<String> first = stream.findFirst();
```
- **findAny()**: 임의의 요소 반환 (병렬 스트림에서 유용)
```java
Optional<String> any = stream.findAny();
```
### 4.2 요소 존재 확인
- **anyMatch()**: 적어도 하나의 요소가 조건을 만족하는지 확인
```java
boolean hasA = stream.anyMatch(s -> s.contains("a"));
```
- **allMatch()**: 모든 요소가 조건을 만족하는지 확인
```java
boolean allLengthGreaterThanTwo = stream.allMatch(s -> s.length() > 2);
```
- **noneMatch()**: 모든 요소가 조건을 만족하지 않는지 확인
```java
boolean hasNoNumbers = stream.noneMatch(s -> s.matches("\\d+"));
```
### 4.3 요소 집계
- **count()**: 요소 개수 반환
```java
long count = stream.count();
```
- **max()**: 최대 요소 반환
```java
Optional<String> max = stream.max(Comparator.naturalOrder());
```
- **min()**: 최소 요소 반환
```java
Optional<String> min = stream.min(Comparator.naturalOrder());
```
### 4.4 요소 리듀싱
- **reduce()**: 모든 요소를 하나의 결과로 리듀스
```java
// 요소 합계
Optional<Integer> sum = stream.reduce((a, b) -> a + b);
// 초기값과 함께 사용
int sum = stream.reduce(0, (a, b) -> a + b);
```
### 4.5 요소 수집
- **collect()**: 요소를 다양한 방식으로 수집
```java
// 리스트로 수집
List<String> list = stream.collect(Collectors.toList());
// 맵으로 수집
Map<Integer, String> map = stream.collect(Collectors.toMap(String::length, s -> s));
```
### 4.6 요소 순회
- **forEach()**: 각 요소에 대해 작업 수행
```java
stream.forEach(System.out::println);
```
- **forEachOrdered()**: 순서를 유지하며 각 요소에 대해 작업 수행
```java
stream.forEachOrdered(System.out::println);
```
반응형
'JAVA' 카테고리의 다른 글
interface 인터페이스 (0) | 2024.10.04 |
---|---|
다형성 Polymorphism (0) | 2024.10.02 |
캡슐화 (0) | 2024.09.25 |
상속(inherence)- extends, super(); (2) | 2024.09.23 |
접근제한자 (1) | 2024.09.23 |