Contents
검색과 매칭
   Sep 24, 2022     3 min read

검색과 매칭

특정 속성이 데이터 집합에 있는지 여부를 검색하는 데이터 처리도 자주 사용된다.

  • 스트림 API
    • allMatch
    • anyMatch
    • noneMatch
    • findFirst
    • findAny

Predicate가 적어도 한 요소와 일치하는가 ?

  • 프레디케이트가 주어진 스트림에서 적어도 한 요소와 일치하는지 확인할 때 : anyMathc메서드를 이용한다.

➡️ menu에 채식요리가 있는지 확인한다

if(menu.stream().anyMatch(Dish::isVegetarian)){
	System.out.println("The menu is (someWhat) vegetarian friendly!!");
}

anyMatch는 불리언을 반환하므로 최종 연산이다.


프레디케이트가 모든 요소와 일치하는 검사

  • allMatch 메서드

스트림의 모든 요소가 주어진 프레디케이트와 일치하는지 검사한다.

예) 메뉴가 건강식(모든 요리가 1000칼로리 이하면 건강식으로 간주하겠다)인지 확인할 수 있다.

boolean isHealthy = menu.stream().allMatch(dish -> dish.getCalories() < 1000);

➡️ 결과 : true


noneMatch

noneMatch는 allMatch와 반대 연산을 수행한다.

noneMatch는 주어진 프레디케이트와 일치하는 요소가 없는지 확인한다.

boolean isHealthy = menu.stream().noneMatch(d -> d.getCalories() >= 1000);

➡️ 결과 : true

  • anyMatch, allMatch, noneMatch 세 메서드는 스트림 쇼트서킷 비법, 즉 자바의 &&, ||와 같은 연산을 활용 활용한다.

요소 검색

  • findAny
    • findAny 메서드는 현재스트림에서 임의의 요소를 반환한다.
    • findAny 메서드를 다른 스트림과 연결해서 사용할 수 있다.

➡️ filter와 findAny를 사용해서 채식요리 선택 예제

Optional<Dish> dish = menu.stream().filter(Dish::isVegetarian).findAny();

스트림 파이프라인은 내부적으로 단일 과정으로 실행할 수 있도록 최적화된다. 즉 쇼트서킷 을 이용해서 결과를 찾는 즉시 실행을 종료한다.

Optional 이란 ? Optional 클래스(java.util.Optional)는 값의 존재나 부재 여부를 표현하는 컨테이너 클래스다. findAny는 아무 요소도 반환하지 않을 수 있다. Optional은 값이 존재하는지 확인하고 값이 값이 없을 때 어떻게 처리할지 강제하는 기능을 제공한다.

isPresent()는 Optional이 값을 포함하면 참(true)을 반환하고 값을 포함하지 않으면 거짓(false)을 반환한다.

isPresent(Consumer block)은 값이 있으면 주어진 블록을 실행한다. Consumer 함수형 인터페이스에는 T 형식의 인수를 받으며 void를 반환하는 람다를 전달할 수 있다.

T get()은 값이 존재하면 값을 반환하고, 값이 없으면 NoSuchElementException을 일으킨다.

T orElse(T other)는 값이 있으면 값을 반환하고, 값이 없으면 기본값을 반환한다.

➡️ 예시) Optional에서는 요리명이 null인지 검사할 필요가 없었다.

menu.stream().filter(Dish::isVegetarian)
                .findAny()
                .ifPresent(dish -> System.out.println(dish.getName()));

첫 번째 요소 찾기

리스트 또는 정렬된 연속 데이터로부터 생성된 스트림처럼 일부 스트림에는 논리적인 아이템 순서가 정해져 있을 수 있다.

이런 스트림에서 첫 번째 요소를 찾으려면 어떻게 해야할까 ?

➡️ 예) 숫자 리스트에는 3으로 나누어떨어지는 첫 번째 제곱값을 반환하는 코드

List<Integer> someNumbers = Arrays.asList(1, 2, 3, 4, 5);
Optional<Integer> firstSquareDivisibleByThree = someNumbers.stream()
										.map(n -> n * n).filter(n -> n % 3 ==0)
										.findFirst();

➡️결과 : 9


findFirst와 FindAny는 언제 사용할까 ?

findFirst와 findAny 메서드가 모두 필요갈까 ? 이유는 병렬성 때문이다. 병렬 실행에서는 첫 번째 요소를 찾기 어렵다. 따라서 요소의 반환 순서가 상관없다면 병렬 스트림에서는 제약이 적은 findAny를 사용한다.