ทั้งคู่เป็น **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 |
| 2 | Type Parameters | 2: T (input), R (output) | 1: T (input) |
| 3 | Abstract Method | R apply(T t) | boolean test(T t) |
| 4 | Return Type | อะไรก็ได้ (R) | แค่ boolean |
| 5 | Use Case | Mapping, Converting, Transforming | Filtering, Validation, Checking |
| 6 | Stream Method | map(), flatMap() | filter(), anyMatch(), allMatch() |
| 7 | Composition | andThen(), 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 super T, ? extends R>
// ใช้กับ 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)
| Generic | Primitive 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; ToIntFunctionstrLength = String::length; IntFunction intToStr = i -> "Num: " + i; IntStream.range(1, 10) .filter(isEven) .mapToObj(intToStr) .forEach(System.out::println);
BiFunction และ BiPredicate (2 Arguments)
| Interface | Method | คำอธิบาย |
|---|---|---|
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 |
BiFunctionconcat = (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 Functionf1 = 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