java / / 2023. 1. 28. 20:33

Java 8 Stream에서 filter를 사용하는 다양한 Predicate

Java 8에서 stream을 사용할 때 filter로 특정 요소를 찾는 다양한 방법을 알아보자.

Predicate: 인수를 받아 boolean 값을 반환하는 함수형 인터페이스이다.
즉, 조건이 참이면 true로 리턴하고, 거짓이면 false로 리턴한다.

stream의 filter는 인수로 Predicate를 받는다.

1. 기본 Predicate를 사용하는 방법

기본적으로 filter를 사용하여 'A'로 시작하는 단어를 찾는 방법이다.

filter는 인수로 Predicate를 받고 찾으려는 람다식을 표현하면 된다.

@Test
public void filterTest() {
  List<String> names = Arrays.asList("James", "Alex", "Alberto", "Robert");
  List<String> result = names.stream()
    .filter(name -> name.startsWith("A"))
    .collect(Collectors.toList());

  Assert.assertTrue(result.size() == 2); // Alex, Alberto
}

2. 두 가지 Predicate를 사용하는 방법

filter가 두 가지 이상일 때는 아래처럼 filter를 체인으로 연속해서 사용하면 된다.

'A'로 시작하고 글자수가 '5글자' 이상인 이름을 찾는 것이다.

@Test
public void filterMultipleTest() {
  List<String> names = Arrays.asList("James", "Alex", "Alberto", "Robert");
  List<String> result = names.stream()
    .filter(name -> name.startsWith("A"))
    .filter(name -> name.length() >= 5)
    .collect(Collectors.toList());

  Assert.assertTrue(result.size() == 1); // Alberto
}

3. 복잡한 Predicate를 사용하는 방법

하나의 filter 안에 연산자를 통해 복잡한 Predicate를 사용하는 방식이다.
방식은 2번과 동일하며 연산자를 통해 참/거짓 조건을 판단하다.

'A'로 시작하고 글자수가 '5글자' 이상인 이름을 찾는 것이다.

@Test
public void filterComplexTest() {
  List<String> names = Arrays.asList("James", "Alex", "Alberto", "Robert");
  List<String> result = names.stream()
    .filter(name -> name.startsWith("A") && name.length() >= 5)
    .collect(Collectors.toList());

  Assert.assertTrue(result.size() == 1); // Alberto
}

4. Predicate and를 사용하는 방법

여러 개의 Predicate를 and로 연결하는 방식이다.

and 조건이 많을 경우 조건식을 따로 구분하여 사용할 수 있으므로 코드를 읽기가 편하다.

'A'로 시작하고 글자수가 '5글자' 이상인 이름을 찾는 것이다.

@Test
public void filterPredicateAndTest() {
  List<String> names = Arrays.asList("James", "Alex", "Alberto", "Robert");
  Predicate<String> startsWithPredicate = str -> str.startsWith("A");
  Predicate<String> lengthPredicate = str -> str.length() >= 5;

  List<String> result = names.stream()
    .filter(startsWithPredicate.and(lengthPredicate))
    .collect(Collectors.toList());

  Assert.assertTrue(result.size() == 1); // Alberto
}

5. Predicate and를 사용하는 방법

Predicate를 or로 연결하는 방식이다.

방식은 4번과 동일하며 조건이 많은 경우 사용하기 좋다.

'A'로 시작하거나 글자수가 '5글자' 이상인 이름을 찾는 것이다.

@Test
public void filterPredicateOrTest() {
  List<String> names = Arrays.asList("James", "Alex", "Alberto", "Robert");
  Predicate<String> startsWithPredicate = str -> str.startsWith("A");
  Predicate<String> lengthPredicate = str -> str.length() >= 5;

  List<String> result = names.stream()
    .filter(startsWithPredicate.or(lengthPredicate))
    .collect(Collectors.toList());

  Assert.assertTrue(result.size() == 4); // James, Alex, Alberto, Robert
}

6. Predicate negate를 사용하는 방법

Predicate에 negate를 사용하는 방식이다.

negate()는 Predicate를 결과를 반대로 바꾸는 것이다. 결과가 true이면 false로, false이면 true로 새로운 Predicate를 리턴한다.

'A'로 시작하거나 글자수가 '5글자' 이상이 아닌 이름을 찾는 것이다.

@Test
public void filterPredicateOrNegateTest() {
  List<String> names = Arrays.asList("James", "Alex", "Alberto", "Robert");
  Predicate<String> startsWithPredicate = str -> str.startsWith("A");
  Predicate<String> lengthPredicate = str -> str.length() >= 5;

  List<String> result = names.stream()
    .filter(startsWithPredicate.or(lengthPredicate.negate()))
    .collect(Collectors.toList());

  Assert.assertTrue(result.size() == 2); // Alex, Alberto
}

7. Predicate를 Inline으로 사용하는 방법

filter 내부에서 Predicate를 and를 사용하여 inline 방식으로 사용하는 방법이다.

'A'로 시작하거나 글자수가 '5글자' 이상인 이름을 찾는 것이다.

@Test
public void filterPredicateInlineTest() {
  List<String> names = Arrays.asList("James", "Alex", "Alberto", "Robert");

  List<String> result = names.stream()
    .filter(
    ((Predicate<String>)(name -> name.startsWith("A")))
    .and(name -> name.length() >= 5)
  )
    .collect(Collectors.toList());

  Assert.assertTrue(result.size() == 1); // Alberto
}

8 . Predicate를 List로 사용하는 방법

여러 개의 Predicate가 있을 때 List에 Predicate를 넣고 filter에서 한번에 사용하는 방법이다. (and 방식)

'A'로 시작하거나 글자수가 '5글자' 이상인 이름을 찾는 것이다.

@Test
public void filterPredicateCollectionTest() {
  List<String> names = Arrays.asList("James", "Alex", "Alberto", "Robert");

  List<Predicate<String>> predicates = Arrays.asList(
    name -> name.startsWith("A"),
    name -> name.length() >= 5
  );

  List<String> result = names.stream()
    .filter(predicates.stream().reduce(x -> true, Predicate::and))
    .collect(Collectors.toList());

  Assert.assertTrue(result.size() == 1); // Alberto
}

참고: https://www.baeldung.com/java-predicate-chain



반응형
  • 네이버 블로그 공유
  • 네이버 밴드 공유
  • 페이스북 공유
  • 카카오스토리 공유