函数式接口
函数式接口是只有一个抽象方法的接口。它们可以有多个默认方法或静态方法。 Java 8引入了函数式接口的概念,使得能够更方便地使用Lambda表达式。 函数式接口可以用于定义高阶函数的参数和返回值。
Predicate<T>
💡 Predicate
接口抽象方法boolean test(T t)
表示接受一个参数并返回一个布尔值
其默认方法来组合成复杂的逻辑运算(与、或、非)
Predicate<String> predicate = (s) -> s.length() > 0;
predicate.test("12345"); // true
predicate.negate().test("12345"); // false
Predicate<Boolean> nonNull = Objects::nonNull;
Predicate<Boolean> isNull = Objects::isNull;
Predicate<String> isEmpty = String::isEmpty;
Predicate<String> isNotEmpty = isEmpty.negate();
// filter **过滤**
List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9, 10);
Predicate<Integer> isEven = n -> n % 2 == 0;
numbers.stream()
.filter(isEven)
.forEach(System.out::println);
// 2,4,6,8
使用场景:
- 在Java 8的流式编程中,它可以用于
filter()
操作,根据指定条件过滤流中的元素。 - 它也可以用于对集合中的元素进行条件判断。
- 或者在代码中执行各种条件性的逻辑。
Function<T, R>
💡 Function
接口抽象方法R apply(T t)
表示接受一个参数(类型T
)并返回一个结果(类型R
)
其默认方法可以用于多个方法组成的方法链
// Function<T, R> 接收一个类型T的参数,返回一个类型R的结果
// lambda 表达式
Function<String, Integer> f1 = (s) -> Integer.valueOf(s);
System.out.println(f1.apply("100")); // 100
// 函数引用(除了方法名外,参数,返回类型一致,可以传入一个函数引用)
Function<String, Double> f2 = Double::valueOf;
System.out.println(f2.apply("100")); // 100.0
// 方法链
// 例如:多次类型转换:String -> Integer -> Double
Function<String, Integer> f1 = Integer::valueOf;
Function<Integer, Double> f2 = Double::valueOf;
f1.andThen(f2).apply("100"); // 100.0
// Function<String, Double> f3 = f1.andThen(f2);
使用场景:
- 在Java 8的流式编程中,它可以用于
map()
操作,将一个流中的每个元素映射为另一个值。 - 它也可以用于将一个类型的数据转换为另一个类型。
- 或者执行任何需要将输入转换为输出的操作。
Consumer<T>
💡 Consumer
接口抽象方法void accept(T t)
表示接受一个参数(类型T
)并且不返回结果的操作
可以对输入的参数进行一系列预定义的流程进行处理
List<String> names = Arrays.asList("Alice", "Bob", "Charlie", "David");
Consumer<String> printName = name -> System.out.println(name);
names.forEach(printName);
使用场景:
- 对集合中的每个元素执行某些操作、对流中的元素进行处理,例如:
- 在Java 8的流式编程中,它可用于
forEach()
操作,对流中的每个元素执行特定操作。
- 在Java 8的流式编程中,它可用于
- 或者执行任何需要消费数据的逻辑。
Supplier<T>
💡 Supplier
接口抽象方法T get()
表示不接收任何参数但返回一个值的方法
// 提供一个无参对象
Supplier<Demo> personSupplier = Demo::new;
personSupplier.get(); // new Demo
// Supplier 提供流的元素
// 生成一个无限长度的流,其中的元素是随机生成的整数
Stream<Integer> randomStream = Stream.generate(() -> new Random().nextInt(100));
// 打印流的前10个元素
Consumer<Integer> action = System.out::println;
randomStream.limit(10).forEach(action);
使用场景:
- 在
Stream
的静态方法generate()
中,可以传递一个Supplier
实例来生成流的元素。generate()
用于生成一个无限长度的流,其元素由提供的Supplier
函数生成。generate()
方法生成的流是无限的,通常需要与limit()
方法结合使用以限制生成的元素数量。
- 在多线程编程中,
Supplier
可以用于获取资源或执行需要延迟计算的任务。
Comparator<T>
💡 Comparator
接口是用于定义对象之间比较逻辑的接口
Comparator
接口抽象方法int compare(T o1, T o2)
表示接受两个参数并返回一个整数
根据返回的整数值的不同,可以确定两个对象的顺序关系。具体规则如下:
- 如果
compare(o1, o2)
返回负数,则表示o1应该排在o2之前。 - 如果
compare(o1, o2)
返回零,则表示o1和o2相等,顺序无所谓。 - 如果
compare(o1, o2)
返回正数,则表示o1应该排在o2之后。
String[] s = {"Alice", "Bob", "Charlie", "David"};
Comparator<String> byLength = Comparator.comparingInt(String::length);
Arrays.sort(s, byLength);
System.out.println(Arrays.toString(s));
使用场景:
对集合进行排序时,可以使用自定义的比较器来指定排序规则。例如:
- 在
Collections.sort()
方法或者Stream.sorted()
操作中,可以传递一个Comparator
实例来指定排序的方式。