: 특정 속성이 데이터 집합에 있는지 여부를 검색하는 데이터 처리도 자주 사용된다. 스트림 API는 allMatch, anyMatch, noneMatch, findFirst, findAny 등 다양한 유틸리티 메서드를 제공한다.
1. 프레디케이트가 적어도 한 요소와 일치하는지 확인
: 만약 프레디케이트가 주어진 스트림에서 적어도 한 요소와 일치하는지 확인할 때 anyMatch 메서드를 이용한다.
: 다음 코드는 menu에 채식요리가 있는지 확인하는 예제다.
if(menu.stream().anyMatch(Dish::isVegetarian)) {
System.out.println("The menu is (somewhat) vegetarian friendly!!");
}
Java
복사
: anyMatch는 불리언을 반환하므로 최종연산이다.
2. 프레디케이트가 모든 요소와 일치하는지 검사
: 프레디케이트가 주어진 스트림에서 모든 요소와 일치하는지 확인할 때 allMatch 메서드를 이용한다.
: 다음 코드는 menu의 모든 요소가 건강식(1000 칼로리 이하)인지 확인하는 예제다.
boolean isHealthy = menu.stream().allMatch(dish -> dish.getCalories() < 1000);
Java
복사
NONEMATCH
: noneMatch는 allMatch와 반대 연산을 수행한다. 즉 noneMatch는 주어진 프레디케이트와 일치하는 요소가 없는지 확인한다.
boolean isHealthy = menu.stream().noneMatch(dish -> dish.getCalories() < 1000);
Java
복사
: anyMatch, allMatch, noneMatch 세 메서드는 스트림 쇼트서킷 기법, 즉 자바의 &&, ||와 같은 연산을 활용한다.
short-circuit evaluation
: 우리가 알고 있는 그거 맞다.
3. 요소 검색
: findAny 메서드는 현재 스트림에서 임의의 요소를 반환한다. findAny 메서드를 다른 스트림 연산과 연결해서 사용할 수 있다.
: 다음처럼 filter와 findAny를 이용해서 채식 요리를 선택할 수 있다.
Optional<Dish> dish = menu.stream()
.filter(Dish::isVegetarian)
.findAny();
Java
복사
: 스트림 파이프라인은 내부적으로 단일 과정으로 실행할 수 있도록 최적화된다.
: 즉 쇼트서킷을 이용해서 결과를 찾는 즉시 실행을 종료한다. 그런데 위 코드에서 사용된 Optional은 뭘까?
Optional이란?
: Optional<T> 클래스(java.util.Optional)는 값의 존재나 부재 여부를 표현하는 컨테이너 클래스다.
: 이전 예제에서 findAny는 nullable하기 때문에 Optional을 이용해서 null 확인 관련 버그를 피할 수 있다.
: 추후 자세히 설명하므로 여기서는 단순히 Optional은 값이 존재하는지 확인하고 값이 없을 때 어떻게 처리할지 강제하는 기능을 제공한다는 사실만 알아두자.
4. 첫 번째 요소 찾기
: 리스트 또는 정렬된 연속적인 데이터 요소로부터 생성된 스트림처럼 일부 스트림에는 논리적인 아이템 순서가 존재할 수 있다.
: 이런 스트림에서 첫 번째 요소를 찾으려면 어떻게 해야 할까?
: 예를 들어 숫자 리스트에서 3으로 나누어떨어지는 첫 번째 제곱값을 반환하는 다음 코드를 살펴보자.
List<Integer> someNumbers = Arrays.asList(1, 2, 3, 4, 5);
Optional<Intger> firstSquareDivisibleByThree = someNumbers.stream()
.map(n -> n * n) // 1, 4, 9, 16, 25
.filter(n -> n % 3 == 0) // 9
.findFirst(); // 9
Java
복사
findFirst와 findAny는 언제 사용할까?
: findFirst와 findAny 메서드가 왜 모두 필요할까. 바로 병렬성 때문이다.
: 두 메서드는 얼핏 같은 동작을 수행한다. 하지만 병렬적인 환경에서는 첫 번째 요소를 판단하기가 어렵다.
: 따라서 요소의 반환 순서가 상관없다면 병렬 스트림에서는 제약이 적은 findAny를 사용한다.