읽기 전에 스트림에 대해 몇 가지만 상기도록하자!!
💡 스트림은 데이터 소스를 변경하지 않는다!
스트림은 데이터 소스로 부터 데이터를 읽기만 할 뿐, 데이터 소스를 변경하지 않는다.
필요에 따라, 정렬된 결과를 컬렉션이나 배열에 담아서 반환한다.
List<String> sortedList = list.stream()
.sorted()
.collect(Collectors.toList());
💡 스트림은 일회용이다.
스트림은 Iterator 처럼 한 번만 탐색할 수 있다.
만약 다시 탐색하고 싶다면 새로운 스트림을 만들어야 한다.
Stream<String> strStream = list.stream();
strStream.forEach(System.out::println);
strStream.forEach(System.out::println); //error. 스트림이 이미 소비되었거나 닫혀있음.
int countOfName = strStream.count(); //error. 스트림이 이미 소비되었거나 닫혀있음.
스트림 필터링: filter 메소드, distinct 메소드
짝수 필터링
List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 2, 3, 4);
Stream<String> stream = numbers.stream()
.filter(i -> i % 2 == 0)
.forEach(System.out::println);
/*
* 결과
* 2
* 4
* 2
* 4
* */
짝수 + 중복 필터링
List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 2, 3, 4);
Stream<String> stream = numbers.stream()
.filter(i -> i % 2 == 0)
.distinct()
.forEach(System.out::println);
/*
* 결과
* 2
* 4
* */
스트림 반환 개수 조작: limit 메소드, skip 메소드
앞에서 n개만 출력
List<Integer> numbers = Arrays.asList(1, 5, 3, 4, 7, 9, 4);
Stream<String> stream = numbers.stream()
.limit(3)
.forEach(System.out::println);
/*
* 결과
* 1
* 5
* 3
* */
앞에서 n개 스킵
List<Integer> numbers = Arrays.asList(1, 5, 3, 4, 7, 9, 4);
Stream<String> stream = numbers.stream()
.skip(3)
.forEach(System.out::println);
/*
* 결과
* 4
* 7
* 9
* 4
* */
스트림 매핑: map 메소드, flatMap 메소드
스트림의 map 메소드는 함수를 인수로 받는다.
이때 인수의 조건에 맞춰 요소들을 변환하여 새로운 스트림을 형성한다.
이름이 담긴 리스트를 이용하여 앞글자가 대문자인 스트림 생성
List<String> names = Arrays.asList("kim", "choo", "park", "oh");
Stream<String> upperNameStream = names.stream()
.map(str -> str.toUpperCase());
이름이 담긴 리스트을 이용하여 이름의 길이를 담은 리스트 생성
List<String> names = Arrays.asList("kim", "choo", "park", "oh");
List<Integer> nameLengths = names.stream()
.map(String::length)
.collect(toList());
flatMap은 하나의 평면화된 스트림을 반환한다.
설명보다는 예시를 보면 바로 이해될 것이다.
이름이 담긴 리스트의 고유 문자를 추출
List<String> names = Arrays.asList("kim", "choo", "oh");
List<Integer> nameLengths = names.stream() //Stream<String>
.map(str -> str.split("")) //Stream<String[]>
.flatMap(Arrays::stream) //Stream<String>
.distinct() //Stream<String>
.collect(toList()); //List<String>
/*
* ["k", "i", "m", "c", "h", "o"]
* */
flatMap 메소드 위와 같이 Stream<String[]> 로 반환되는 값을 Stream<String>로 반환할 수 있도록 모든 스트림을 하나의 스트림으로 연결하는 기능을 수행한다.
스트림 정렬: sorted 메소드
오름차순 정렬
List<String> names = Arrays.asList("kim", "choo", "park", "oh");
List<Integer> sortedNames = names.stream()
.sorted()
.collect(toList());
/*
* ["kim", "choo", "oh", "park"]
* */
내림차순 정렬
List<Integer> sortedNames = names.stream()
.sorted(Comparator.reverseOrder())
.collect(toList());
/*
* ["park", "oh", "choo", "kim"]
* */
스트림 검색: allMatch, anyMatch, noneMatch, findFirst, findAny 메소드
적어도 한 요소와 일치하는지 확인: anyMatch 메소드
boolean correct = numbers.stream()
.anyMatch(a -> a % 2 == 0);
모든 요소와 일치하는지 확인: allMatch 메소드
boolean correct = numbers.stream()
.allMatch(a -> a % 2 == 0);
모든 요소와 불일치하는지 확인: noneMatch 메소드
boolean correct = numbers.stream()
.noneMatch(a -> a % 2 != 0);
첫 번째 요소 찾기: findFirst, findAny 메소드
Optional<Integer> firstNumberDivisibleByTwo = numbers.stream()
.filter(number -> number % 2 == 0)
.findFirst();
firstNumberDivisibleByTwo.ifPresent(number -> System.out.println(number));
※ findFirst 메소드와 findAny 메소드의 차이
findFirst 메소드와 findAny메소드는 filter 조건에 일치하는 요소 1개를 반환한다. 만약 조건이 없다면 요소 첫 번째를 반환한다.
그럼 findFirst 메소드와 findAny 메소드의 기능이 똑같은 거이 아니냐 라고 물을 수 있다. 이는 Stream을 직렬로 처리할 때는 맞는말이다.
하지만 Stream을 병렬로 처리할 때는 findFirst()는 여러 요소가 조건에 부합해도 Stream은 순서를 고려하여 가장 처음 일치하는 요소를 리턴한다.
반면에 findAny는 모든 요소를 참조하기 때문에 병렬 처리시 가장 먼저 찾게 되는 요소가 계속 바뀌게 되기 때문에 반환값이 계속 달라질 수 있다.
따라서 요소의 반환 순서가 상관 없다면 병렬 스트림에서는 제약이 적은 findAny를 사용하고
반환 순서가 상관있다면 findFirst를 사용한다.
※Optional이란?
https://yeo-computerclass.tistory.com/387
스트림 결과내기: max, min, sum, average, count 메소드
리스트의 총합
long sum = LongStream.of(1, 2, 3, 4, 5)
.sum();
나머지 메소드들도 위와 같은 형식을 적용 가능하다.
스트림 리듀싱: reduce 메소드
모든 숫자 더하기
int sum = IntStream.rangeClosed(1, 4)
.reduce(5, (a, b) -> a + b);
int sum = IntStream.rangeClosed(1, 4)
.reduce(5, Integer::sum);
/*
* 15
* */
위 두 개 식은 같은 코드이다. reduce 메소드의 첫 번째 파라미터는 초깃값이다.
최댓값 구하기
List<Integer> numbers = Arrays.asList(4, 9 ,2);
Optional<Integer> max = numbers.stream()
.reduce((x, y) -> x > y ? x : y);
Optional<Integer> max = numbers.stream()
.reduce(Integer::max);
/*
* 9
* */
'Java' 카테고리의 다른 글
JAVA ThreadPoolExecutor을 이용한 스레드 풀(Thread Pool) (0) | 2023.05.25 |
---|---|
Optional이란? (0) | 2022.12.05 |
[Java] 스트림 생성 (리스트, 배열을 스트림으로, 숫자 범위로부터 스트림, 파일로부터 스트림) (0) | 2022.12.05 |
[Java] 변수명, 메소드명 작성법 (0) | 2022.10.29 |
[Java] SOLID: 객체 지향 설계 5원칙 (0) | 2022.07.23 |