일반적으로 술어는 값이 참인지 거짓인지를 결정하는 진술을 의미합니다. 프로그래밍 술어는 부울 값을 반환하는 하나의 인수가 있는 함수를 의미합니다. Functional Interface Predicate는 Java 8에서 실현되었습니다. "Functional"은 하나의 추상 메서드만 포함한다는 의미입니다. 인수를 수락하고 부울을 반환합니다. Java에서 기능 인터페이스는 Lambda 표현식, 생성자 및 메서드 참조를 처리하는 데 사용됩니다. 일반적으로 Java 8 술어는 오브젝트 콜렉션에 대한 필터를 적용하는 데 사용됩니다. 주요 응용 프로그램과 널리 사용되는 방법을 살펴보고 일부 연습 문제를 해결해 봅시다.
개발자가 술어를 사용하는 이유
기본적으로 개발자는 미리 정의된 기준에 따라 항목을 평가하고 부울 값을 반환하는 모든 작업에 조건자를 사용할 수 있습니다. 다음은 술어를 사용하여 개발자가 처리하는 간단한 작업의 예입니다.- 정수 집합 필터링.
- 데이터가 사전 정의된 여러 조건을 준수하는지 확인하여 목록 정렬(예: 가격 및 중량 조건을 설정하여 품목 범위 구성).
- 동시 프로그래밍에서 유틸리티 패키지 사용.
Java의 술어 구문
java.util.function.Predicate는 Lambda에서 평가 노출을 처리하는 대체 방법으로 Java 8에서 도입되었습니다. 인터페이스의 표준 보기는 Predicate<T> 입니다 . 여기서 T는 부울 값을 반환하는 단일 인수입니다. Java 술어에는 주어진 객체에서 이 술어를 평가하는 기능적(추상) 메소드 test(Object)가 있습니다.
@FunctionalInterface
public interface Predicate<T> {
boolean test(T t);
}
다음은 "보다 큼", "보다 작음" 조건에 따라 정수를 필터링하는 간단한 조건자를 작성하는 예입니다.
// An example of a simple Java predicate
import java.util.function.Predicate;
public class PredicateExample {
public static void main(String[] args)
{
// Creating predicate
Predicate<Integer> lesserThan = i -> (i < 18);
// Calling Predicate method
System.out.println(lesserThan.test(10));
}
}
출력은 10 < 18이기 때문에 참이 됩니다 . filter() 에 술어가 있는 또 다른 예입니다 . 술어는 연령 목록에서 모든 성인을 필터링하는 데 도움이 됩니다.
import java.util.List;
import java.util.function.Predicate;
public class PredicateExample {
public static void main(String[] args) {
List<Integer> ages = List.of(17, 18, 19, 28, 18, 28, 46, 7, 8, 9, 21, 12);
NotLessThan18<Integer> isAdult = new NotLessThan18<>();
ages.stream().filter(isAdult).forEach(System.out::println);
}
}
class NotLessThan18<E> implements Predicate<Integer> {
@Override
public boolean test(Integer v) {
Integer ADULT = 18;
return v >= ADULT;
}
}
출력은 다음과 같습니다.
18 19 28 18 28 46 21
Java 8 조건자 메서드
술어 인터페이스에는 몇 가지 메소드가 있습니다.- boolean test(T t)는 주어진 인수에 대한 술어를 평가합니다.
- default Predicate<T> and(Predicate<? super T> other)는 이 술어와 다른 술어의 단락 논리적 AND를 나타내는 술어를 반환합니다.
- default Predicate<T> 또는 이 술어와 다른 술어의 단락 논리적 OR을 나타내는 구성된 술어를 반환합니다.
- default Predicate<T> negate()는 이 술어와 논리적으로 반대되는 술어를 반환합니다.
- default Predicate<T> isEqual(Object targetRef) 는 Objects.equals(Object, Object) 에 따라 두 인수가 같은지 테스트한 결과를 반환합니다 .
불리언 테스트(T t)
이것은 주어진 인수가 술어의 조건을 만족하는지 여부를 평가하는 Java 술어에 대한 기능적 방법입니다. 예: 여기서는 18세 이상의 모든 사람을 위한 술어 adult를 만듭니다. test() 메서드는 정수 값을 가져와서 확인합니다.
import java.util.function.Predicate;
public class PredicateTestTest {
public static void main(String[] args) {
Predicate<Integer> adult = i -> i >= 18;
System.out.println(adult.test(12));
System.out.println(adult.test(19));
System.out.println(adult.test(21));
}
}
위 코드의 출력은 어떻게 될까요? 첫 번째 경우에는 12가 18보다 작으므로 false가 됩니다. 두 번째와 세 번째 시나리오는 조건이 충족되어 반환이 true가 됩니다.
거짓 참 참
기본 Predicate.and()
이 메서드는 "and" 연산자를 나타냅니다. 그렇기 때문에 주어진 술어 중 하나가 설정된 조건을 준수하지 않으면 다른 술어는 평가를 받지 않습니다. 예: and() 를 사용하여 이미 성인이지만 65세 미만인 모든 사람을 필터링하는 술어를 Java로 작성해 보겠습니다 . predicate.add()를 사용 하고 이러한 조건에 대해 람다로 Java 조건자를 작성해 보겠습니다. 조건이 참이면 앱은 다음 문을 반환합니다.
import java.util.function.Predicate;
public class PredicateDemo {
public static void main(String[] args) {
Predicate<Integer> adultYet = i -> i >= 18;
Predicate<Integer> adultStill = i -> i < 65;
System.out.println(adultYet.and(adultStill).test(5));
System.out.println(adultYet.and(adultStill).test(38));
System.out.println(adultYet.and(adultStill).test(90));
}
}
출력은 다음과 같습니다.
거짓 참 거짓
기본 Predicate.or()
Predicate.or() 메서드는 "OR" 연산자를 나타냅니다. 이것은 두 술어 중 하나가 참이고 다른 하나가 거짓이더라도 조건이 참으로 유지됨을 의미합니다. 예: 이제 문자열을 평가해 보겠습니다. 하위 문자열 "my" 또는 "crayon"이 포함된 모든 구문을 정렬하려면 OR 방법을 사용해 보십시오.
import java.util.function.Predicate;
public class PredicateDemo2 {
public static void main(String[] args) {
Predicate<String> containsA = t -> t.contains("crayon");
Predicate<String> containsB = t -> t.contains("my");
System.out.println(containsA.or(containsB).test("here is my crayon"));
System.out.println(containsA.or(containsB).test("here is my pencil"));
System.out.println(containsA.or(containsB).test("here is John's crayon"));
System.out.println(containsA.or(containsB).test("here is John's pencil"));
}
}
출력은 다음과 같습니다.
참 참 참 거짓
기본 술어 부정()
부정() 메서드는 사전 정의된 기준을 준수하지 않는 모든 값을 수집하는 데 사용됩니다. 예: "Tomatoes" 클래스를 통해 정렬하고 "Red"가 아닌 모든 항목을 찾으려면 술어를 작성하고 전체 시퀀스를 빠르게 스캔할 수 있습니다. 이 코드를 직접 작성하고 완료되면 솔루션과 비교하여 확인하십시오.
import java.util.function.Predicate;
public class PredicateDemo3 {
public static void main(String[] args) {
Predicate<Integer> adult = i -> i >= 18;
System.out.println(adult.negate().test(7)); System.out.println(adult.negate().test(19))
}
}
출력은 다음과 같습니다.
허위 사실
정적 술어 isEqual(Object targetRef)
이 메서드는 두 개체가 Objects.equals()의 매개 변수로 정의된 값과 같은지 확인하려는 경우 매우 유용합니다. 이 방법은 유사한 테스트 결과를 비교해야 하는 경우에 특히 유용합니다. 예: 두 개의 배 마차를 비교하고 두 마차에 표준 무게와 색상의 과일이 있는지 확인하려고 한다고 가정해 봅시다. 이 경우 정적 술어 isEqual(Object targetRef)가 정확히 필요한 메소드입니다. isEqual이 두 문자열의 동등성을 확인하는 방법을 살펴보겠습니다 .
import java.util.function.Predicate;
public class PredicateDemo2 {
public static void main(String[] args) {
Predicate<String> i = Predicate.isEqual("here is my crayon");
System.out.println(i.test("here is my pencil"));
System.out.println(i.test("here is my crayon"));
}
}
분석 중인 개체가 표준 조건을 준수하는 경우 함수는 true를 반환합니다. 출력은 다음과 같습니다.
거짓 참
자바 IntPredicate
Java IntPredicate는 기능적 인터페이스이므로 이를 람다 식 또는 메서드 참조에 대한 할당 대상으로 사용할 수 있습니다. IntPredicate는 정수에서 작동하며 조건에 따라 조건자 값을 반환합니다. 술어 인터페이스와 같이 IntPredicate에도 test() , and() , negate() 또는 () 메서드가 있습니다. 다음은 IntPredicate의 예입니다. 또한 어레이에서 모든 성인(18세 이상)을 필터링합니다.
import java.util.Arrays;
import java.util.function.IntPredicate;
public class IntPredicateExample {
public static void main(String[] args) {
int[] ages = { 18, 28, 18, 46, 90, 45, 2, 3, 1, 5, 7, 21, 12 };
IntPredicate p = n -> n >= 18;
Arrays.stream(ages).filter(p).forEach(System.out::println);
}
}
출력은 다음과 같습니다.
18 28 18 46 90 45 21
Java에서 깨끗한 조건자 작성
Java 술어는 기능이 뛰어나고 작업하기에 재미있습니다. 그러나 작성하는 람다 표현식이 코드에 미치는 영향을 염두에 두지 않으면 지저분한 조건자로 코드 유지 관리 가능성이 감소할 위험이 있습니다. 다음은 기능 인터페이스를 쉽게 관리하고 읽을 수 있도록 도와주는 몇 가지 간단한 방법입니다.- Don't Repeat Yourself — 두 번 이상 반복되는 값, 메서드 및 조건을 사용하여 Java로 술어를 구성하지 마십시오. 이런 식으로 생산적인 시간을 낭비하고 코드를 지저분하게 만듭니다.
- 테스트 가능성을 보장하기 위해 앱 코드에서 조건자를 분리합니다. 그 외에는 술어 단위 테스트 일정을 만들고 이를 고수하십시오.
- 가져오기 및 컴포지션 패턴을 사용하여 클래스가 부풀어 오르지 않고 쉽게 관리할 수 있도록 합니다.
- Java 술어를 Helper 클래스로 이동하는 것을 고려하십시오. 이렇게 하면 코드의 재사용성이 향상되고 유지 관리가 용이해집니다.
- 가독성 - 가능하면 복잡한 술어보다 한 줄 문장을 선호합니다. 복잡한 기능 인터페이스에 대한 이해를 과시하고 싶을 수도 있습니다. 그러나 유지 관리에 있어서는 적을수록 좋습니다.
GO TO FULL VERSION