[JAVA] Predicate

신명철·2022년 10월 20일
0

JAVA

목록 보기
12/14

Predicate ?

arugment를 받아서 boolean type을 반환하는 Functional Interface

1. test()

public class Main {
	public static void main(String[] args) {
		Predicate<Integer> predicate = (num) -> num > 10;
		
		boolean result = predicate.test(100);
		
		System.out.println(result); // true
	}
}

2. and() & or()

public class Main {

	public static void main(String[] args) {
		Predicate<Integer> predicate1 = (num) -> num > 10;
		Predicate<Integer> predicate2 = (num) -> num < 50;
		
        // and()
		boolean result1 = predicate1.and(predicate2).test(30);
		System.out.println("10 < 30 < 50 ? =>" + result); // true
        
        // or()
        boolean result2 = predicate1.or(predicate2).test(5);
		System.out.println(" 10 > 5 or  5 < 50 ? =>" + result2); // true
	}
}

3. isEqual()

public class Main {
	public static void main(String[] args) {
		Stream<Integer> stream = IntStream.range(10, 100).boxed();
	
		stream.filter(Predicate.isEqual(20))
				.forEach(System.out::println); // 20
	}
}

4. negate()

public class Main {
	public static void main(String[] args) {
		Predicate<Integer> predicate = (num) -> num > 0;
		boolean result = predicate.negate().test(-1);
		System.out.println("-1 is bigger than 0 ? => " + result); // true
	}
}
  • 반대 결과값 return

5. Stream

public class Main {
	public static void main(String[] args) {
		Predicate<Integer> predicate = (num) -> num % 2 == 0;
		
		Stream<Integer> stream = IntStream.range(10, 20).boxed();
		
		stream.filter(predicate).forEach(System.out::println); 
	}
}
10,12,14,16,18 // 출력 내용
  • Predicate를 사용하면 Stream의 filter로 사용할 수 있다는 장점이 있음

Predicate Chain

Stream에 Predicate를 적용해보자.

1. Predicate를 사용하지 않은 형태

public static void main(String[] args) {
	List<String> result = names.stream()
		.filter(name -> name.startsWith("김") && name.length() < 3)
		.collect(Collectors.toList());
}
  • 김 씨이며 이름이 2 글자인 이름을 찾아내는 Stream 이다.

2. Predicate 적용

public static void main(String[] args) {
	Predicate<String> startsWithKim = (name) -> name.startsWith("김");
	Predicate<String> shorterThanThree = (name) -> name.length() < 3;
		
	List<String> result = names.stream()
		.filter(startsWithKim.and(shorterThanThree))
		.collect(Collectors.toList());
}
  • and() 연산을 활용해서 코드가 짧아졌지만 가독성이 더 좋은지....는 모르겠다
  • 굳이 따로 Predicate를 따로 선언할 필요 없이 아래 코드와 같이 Inline으로 작성할 수도 있다
public static void main(String[] args) {
	List<String> result = names.stream()
		.filter(
				((Predicate<String>)name -> name.startsWith("김"))
				.and(name -> name.length() < 3))
		.collect(Collectors.toList());
}
  • 오히려 이해하기 더 힘들어진 것 같은 기분이 드는건 왜일까

3. Predicate Collection

public static void main(String[] args) {
	List<Predicate<String>> predicates = new ArrayList<>();
	predicates.add(name -> name.startsWith("김"));
	predicates.add(name -> name.length() < 3);

	List<String> result = names.stream()
			.filter(predicates.stream().reduce(x->true, Predicate::and))
			.collect(Collectors.toList());
}
  • Predicate 를 Collection 으로 만들어서 Stream으로 filter에 집어넣을 수도 있다.
  • or() 를 사용하는 경우는 다음과 같이 작성할 수도 있다.
public static void main(String[] args) {
	List<Predicate<String>> predicates = new ArrayList<>();
	predicates.add(name -> name.startsWith("김"));
	predicates.add(name -> name.length() < 3);
	
    // 김씨이거나 2글자인 이름
	List<String> result = names.stream()
			.filter(predicates.stream().reduce(x->false, Predicate::or))
			.collect(Collectors.toList());
}




=> 조건 분기가 잦은 상황에서 사용하면 여기저기 재사용 하면서 유용하게 사용할 수 있을 것 같다 :)

profile
내 머릿속 지우개

0개의 댓글