컬렉션의 저장 요소를 하나씩 참조해서 람다식으로 참조할 수 있는 반복자
기존에는 많은 양의 데이터를 다룰 때 배열이나 컬렉션에 데이터를 담고 for문과 Iterator를 돌림
but, 재사용성이 떨어지고 코드 길어짐
람다식으로 처리
public static void main(String[] args) {
List<Integer> numList = new ArrayList<>(Arrays.asList(1, 2, 3, 4, 5));
Stream<Integer> carStream = numList.stream();
carStream.forEach(s -> {
System.out.println(s);
});
}
원본의 데이터를 변경하지 않는다.
내부 반복자를 사용하여 병렬 처리가 쉽다
중간 처리와 최종 처리가 가능
대량의 데이터를 가공해서 축소하는 것을 reduction
이라고 한다 (평균값, 최대값, 합계 … )
이러한 리덕션을 바로 할 수 없을 때 집계하기 좋도록 중간 처리가 필요
파이프라인은 여러개의 스트림이 연결되어 있는 형태로 최종 처리를 제외하고는 모두 중간 처리 스트림이다.
Stream 인터페이스는 많은 중간처리 메소드가 있는데, 이 메소드들은 중간처리 된 스트림을 반환한다.
List<Integer> numList = new ArrayList<>(Arrays.asList(1, 2, 3, 8, 4, 3, 3, 6, 9));
Stream<Integer> carStream = numList.stream();
Optional<Integer> first = carStream
.distinct() // 중간처리
.filter(x -> x > 4) // 중간처리
.sorted() // 중간처리
.findFirst(); // 최종 처리
- 요소를 대체하는 스트림을 생성할 때
flatMap
public static void main(String[] args) {
List<String> inputList = Arrays.asList("hello java", "hello spring");
Stream<String> stream = inputList.stream().map(s -> s.toUpperCase());
System.out.println(stream.toList()); // [JAVA, SPRING]
Stream<String> stream = inputList.stream().flatMap(data -> Arrays.stream(data.split(" ")));
System.out.println(stream.toList()); // [hello, java, hello, spring]
}
스트림에 영향을 주지 않으면서 특정 연산을 수행할 때 (ex. 중간에 출력을 하고 싶을 때)
stream의 요소들을 List, Set, Map 등 다른 종류의 결과로 수집할 때 사용
Collector 타입을 인자로 받아 처리한다.
List<String> inputList = Arrays.asList("hello java", "hello spring");
List<String> collect = inputList.stream().map(s -> s.toUpperCase()).collect(Collectors.toList());
System.out.println(collect);
특정한 조건을 충족하는지 검사, boolean으로 반환
List<String> inputList = Arrays.asList("hello java", "hello spring");
boolean match = inputList.stream().map(s -> s.toUpperCase()).anyMatch(name -> name.contains("HELLO"));
System.out.println(match);
스트림은 재사용할 수 없다
for-loop 보다 느리다고 함
스트림을 사용하면서 람다나 메서드 참조를 사용하는 경우에는 지역 변수를 사용할 수 없다.
Arrays.stream(new String[]{"c", "python", "java"})
.filter(word -> {
System.out.println("Call filter method: " + word);
return word.length() > 3;
})
.map(word -> {
System.out.println("Call map method: " + word);
return word.substring(0, 3);
}).findFirst();
이와 같은 상황에서 출력 결과를 보면
Call filter method: c
Call filter method: python
Call map method: python
이렇게 나온다. 왜냐.!! 각 스트림 중간 연산 조건에 만족하면 바로 밑으로 내려가기 때문에 그리고 최종 연산이 하나만 찾는 것이기 때문에 java는 가지도 않는다. (만약 최종 연산이 그냥 출력으로 바뀌었으면 python 이후에 java도 출력될것이다)
위와 같은 스트림 동작 순서를 알고 있으면 스트림 동작을 최소화 시켜 성능 개선에 도움이 될것이다!