Computer >> บทช่วยสอนคอมพิวเตอร์ >  >> การเขียนโปรแกรม >> Java

ความแตกต่างระหว่าง Function และ Predicate ใน Java 8 Functional Interfaces

ทั้งคู่เป็น **Functional Interfaces** (มีเพียง 1 abstract method) ใน package java.util.function ใช้สำหรับ Functional Programming และ Streams

ตารางเปรียบเทียบ

ลำดับหัวข้อFunction<T, R>Predicate<T>
1พื้นฐาน**Transformation**: รับ Input → คืน Output (อาจชนิดต่างกัน)**Condition Test**: รับ Input → คืน boolean
2Type Parameters2: T (input), R (output)1: T (input)
3Abstract MethodR apply(T t)boolean test(T t)
4Return Typeอะไรก็ได้ (R)แค่ boolean
5Use CaseMapping, Converting, TransformingFiltering, Validation, Checking
6Stream Methodmap(), flatMap()filter(), anyMatch(), allMatch()
7CompositionandThen(), compose()and(), or(), negate()

Function<T, R> - Transformation

import java.util.function.Function;

public class FunctionExample {
    public static void main(String[] args) {
        // Function - String ใน, Integer ออก
        Function strLength = s -> s.length();
        System.out.println("Length: " + strLength.apply("Hello")); // 5
        
        // Function - Integer ใน, String ออก
        Function intToStr = i -> "Number: " + i;
        System.out.println(intToStr.apply(42)); // Number: 42
        
        // Chaining: andThen (left to right)
        Function lengthThenDouble = strLength.andThen(l -> l * 2);
        System.out.println("Double length: " + lengthThenDouble.apply("Hi")); // 4
        
        // Chaining: compose (right to left)
        Function doubleThenLength = strLength.compose(i -> i * 2);
        // ไม่ทำงานเพราะ compose ต้องการ Function
        
        // ใช้กับ Stream map()
        List words = List.of("Apple", "Banana", "Cherry");
        List lengths = words.stream()
            .map(strLength) // หรือ .map(String::length)
            .toList();
        System.out.println(lengths); // [5, 6, 6]
    }
}

Predicate<T> - Condition Testing

import java.util.function.Predicate;

public class PredicateExample {
    public static void main(String[] args) {
        // Predicate - String ใน, boolean ออก
        Predicate isLong = s -> s.length() > 5;
        Predicate startsWithA = s -> s.startsWith("A");
        
        System.out.println("isLong.test(\"Hello\"): " + isLong.test("Hello")); // false
        System.out.println("isLong.test(\"World!\"): " + isLong.test("World!")); // true
        
        // Composition: and, or, negate
        Predicate longAndStartsWithA = isLong.and(startsWithA);
        Predicate longOrStartsWithA = isLong.or(startsWithA);
        Predicate notLong = isLong.negate();
        
        System.out.println("Long AND starts with A (\"Apple\"): " + longAndStartsWithA.test("Apple")); // false (5 not >5)
        System.out.println("Long OR starts with A (\"Apple\"): " + longOrStartsWithA.test("Apple"));  // true
        System.out.println("NOT Long (\"Hi\"): " + notLong.test("Hi")); // true
        
        // ใช้กับ Stream filter()
        List words = List.of("Apple", "Banana", "Cherry", "Date", "Elderberry");
        List longWords = words.stream()
            .filter(isLong)
            .toList();
        System.out.println(longWords); // [Banana, Cherry, Elderberry]
    }
}

Primitive Specializations (หลีกเลี่ยง Boxing)

GenericPrimitive Specializations
Function<T, R>IntFunction<R>, LongFunction<R>, DoubleFunction<R>
ToIntFunction<T>, ToLongFunction<T>, ToDoubleFunction<T>
IntToLongFunction, IntToDoubleFunction, LongToIntFunction, ...
Predicate<T>IntPredicate, LongPredicate, DoublePredicate
// ใช้ Primitive versions สำหรับ performance
IntPredicate isEven = i -> i % 2 == 0;
ToIntFunction strLength = String::length;
IntFunction intToStr = i -> "Num: " + i;

IntStream.range(1, 10)
    .filter(isEven)
    .mapToObj(intToStr)
    .forEach(System.out::println);

BiFunction และ BiPredicate (2 Arguments)

InterfaceMethodคำอธิบาย
BiFunction<T, U, R>R apply(T t, U u)รับ 2 inputs → 1 output
BiPredicate<T, U>boolean test(T t, U u)รับ 2 inputs → boolean
BinaryOperator<T>T apply(T t1, T t2)Function<T, T> แบบ 2 inputs ชนิดเดียวกัน
UnaryOperator<T>T apply(T t)Function<T, T> แบบ 1 input
BiFunction concat = (a, b) -> a + " " + b;
System.out.println(concat.apply("Hello", "World")); // Hello World

BiPredicate hasLength = (s, len) -> s.length() == len;
System.out.println(hasLength.test("Hi", 2)); // true

BinaryOperator sum = (a, b) -> a + b;
System.out.println(sum.apply(10, 20)); // 30

Method References กับ Function/Predicate

// Function
Function f1 = String::length;           // Method reference
Function f2 = String::toUpperCase;       // Instance method
Function f3 = MyClass::staticMethod;     // Static method
Function f4 = MyClass::new;             // Constructor

// Predicate
Predicate p1 = String::isEmpty;                  // Instance method
Predicate p2 = s -> s.startsWith("A");           // Lambda (complex)
Predicate> p3 = Collection::isEmpty;       // Interface method

สรุป

  • Function = **Transform** (Input → Output) → ใช้กับ map()
  • Predicate = **Test** (Input → boolean) → ใช้กับ filter()
  • ทั้งคู่รองรับ **Composition** (Function: andThen/compose, Predicate: and/or/negate)
  • ใช้ **Primitive specializations** สำหรับ performance critical code