Java 函数式编程提供了强大的工具,尤其是在处理函数式接口时,Consumer
、Supplier
、Function
和 Predicate
是四大核心接口。这些接口结合泛型和方法引用,使 Java 代码更加简洁高效。本篇文档将深入探讨四大函数式接口的使用方式及其与泛型结合的高级应用。
Consumer<T>
Consumer
接口接收一个输入参数并对其进行操作,不返回任何结果。它适合用于打印、日志记录或修改对象的操作。
void accept(T t)
Consumer<String> printer = System.out::println;
printer.accept("Hello, World!");
andThen
方法将多个 Consumer
组合。Consumer<String> printer = System.out::println;
Consumer<String> logger = s -> System.out.println("Logging: " + s);
Consumer<String> combined = printer.andThen(logger);
combined.accept("Test");
// 输出:
// Test
// Logging: Test
List<String> names = Arrays.asList("Alice", "Bob", "Charlie");
names.forEach(System.out::println);
// 输出:
// Alice
// Bob
// Charlie
Supplier<T>
Supplier
接口不接受任何参数,返回一个结果。它通常用于延迟计算或对象的懒加载。
T get()
Supplier<Double> randomSupplier = Math::random;
System.out.println(randomSupplier.get()); // 输出一个随机数
Supplier<String> defaultSupplier = () -> "Default Value";
Optional<String> optional = Optional.ofNullable(null);
System.out.println(optional.orElseGet(defaultSupplier));
// 输出:Default Value
Supplier<List<String>> lazyList = () -> Arrays.asList("A", "B", "C");
System.out.println(lazyList.get());
// 输出:[A, B, C]
Function<T, R>
Function
接口接收一个输入并返回一个输出,常用于数据转换或值映射。
R apply(T t)
Function<Integer, String> intToString = Object::toString;
System.out.println(intToString.apply(42)); // 输出:42
andThen
和 compose
方法组合多个 Function
。Function<Integer, Integer> square = x -> x * x;
Function<Integer, String> toString = Object::toString;
Function<Integer, String> combined = square.andThen(toString);
System.out.println(combined.apply(4)); // 输出:16
List<Integer> numbers = Arrays.asList(1, 2, 3);
List<String> results = numbers.stream()
.map(x -> x * x)
.map(Object::toString)
.collect(Collectors.toList());
System.out.println(results); // 输出:[1, 4, 9]
Predicate<T>
Predicate
接口用于条件判断,返回布尔值。它常用于过滤或验证操作。
boolean test(T t)
Predicate<String> isNotEmpty = s -> s != null && !s.isEmpty();
System.out.println(isNotEmpty.test("Hello")); // true
and
、or
和 negate
方法组合多个 Predicate
。Predicate<String> isShort = s -> s.length() < 5;
Predicate<String> startsWithA = s -> s.startsWith("A");
System.out.println(isShort.and(startsWithA).test("Apple")); // false
System.out.println(isShort.or(startsWithA).test("Apple")); // true
System.out.println(isShort.negate().test("Apple")); // true
List<String> names = Arrays.asList("Alice", "Bob", "", "Charlie");
names.stream()
.filter(s -> !s.isEmpty())
.forEach(System.out::println);
// 输出:
// Alice
// Bob
// Charlie
通过泛型方法,可以定义通用的逻辑操作,从而使代码更加灵活和可重用。
public static <T> void process(T value, Consumer<T> action) {
action.accept(value);
}
process("Generic", System.out::println);
// 输出:Generic
通过限定泛型类型的边界,确保类型安全。
public static <T extends Number> T add(T a, T b, Function<T, T> adder) {
return adder.apply(a);
}
Function<Integer, Integer> increment = x -> x + 1;
System.out.println(add(1, 2, increment)); // 输出:3
结合方法引用,可以进一步简化泛型方法的实现。
public static <T> T getDefault(Supplier<T> supplier) {
return supplier.get();
}
System.out.println(getDefault(() -> "Hello")); // 输出:Hello
通过泛型方法和函数式接口的结合,可以有效减少重复代码,提高代码复用性。
public class TestMethod {
@Data
@AllArgsConstructor
static class Person {
private String personName;
}
@Data
@AllArgsConstructor
static class Animal {
private String animalName;
}
public static <T, R> List<R> getName(List<T> nameList, Function<T, R> nameExtractor) {
return nameList.stream().map(nameExtractor).collect(Collectors.toList());
}
public static void main(String[] args) {
List<Person> peopleList = Arrays.asList(new Person("张三"), new Person("李四"));
List<Animal> animalList = Arrays.asList(new Animal("狗"), new Animal("猫"));
getName(peopleList, Person::getPersonName).forEach(System.out::println);
getName(animalList, Animal::getAnimalName).forEach(System.out::println);
}
}
通过 Supplier
进行延迟计算或资源加载。
Supplier<List<String>> lazyList = () -> Arrays.asList("A", "B", "C");
System.out.println(lazyList.get());
// 输出:[A, B, C]
结合 Function
和 Predicate
构建数据处理流水线。
List<String> names = Arrays.asList("Alice", "Bob", "", "Charlie");
names.stream()
.filter(s -> !s.isEmpty())
.map(String::toUpperCase)
.forEach(System.out::println);
// 输出:
// ALICE
// BOB
// CHARLIE
通过函数式接口动态实现策略。
public static <T> T execute(T input, Function<T, T> strategy) {
return strategy.apply(input);
}
Function<Integer, Integer> doubleIt = x -> x * 2;
System.out.println(execute(5, doubleIt));
// 输出:10
通过泛型和 Function
实现灵活的数据映射。
public static <T, R> List<R> map(List<T> list, Function<T, R> mapper) {
return list.stream().map(mapper).collect(Collectors.toList());
}
List<Integer> numbers = Arrays.asList(1, 2, 3);
List<String> strings = map(numbers, Object::toString);
System.out.println(strings);
// 输出:["1", "2", "3"]
这份文档详细介绍了四大函数式接口及其结合泛型的高级用法,涵盖从基础到高级的使用场景,帮助开发者更高效地利用 Java 的函数式编程能力。