这一节学一下用得比较多的三个函数式接口:
--Predicate
--Consumer
--Function
Predicate
java.util.function.Predicate
public static <T> List<T> filter(List<T> list, Predicate<T> p) {
List<T> results = new ArrayList<>();
for(T s: list){
if(p.test(s)){
results.add(s);
}
}
return results;
}
List<String> listOfStrings = new ArrayList<>();
listOfStrings.add("");
listOfStrings.add("a");
Predicate<String> nonEmptyStringPredicate = (String s) -> !s.isEmpty();
List<String> nonEmpty = filter(listOfStrings, nonEmptyStringPredicate);
nonEmpty.forEach(System.out::println);
剩余两个函数就不一一举例了。
Consumer
java.util.function.Consumer
Function
java.util.function.Function<T, R>接口定义了一个叫作apply的方法,它接受一个泛型T的对象,并返回一个泛型R的对象。
拓展: 原始类型特化
在Java里有一个将原始类型转换为对应的引用类型的机制。这个机制叫作装箱(boxing)。相反的操作,也就是将引用类型转换为对应的原始类型,叫作拆箱(unboxing)
装箱后的值本质上就是把原始类型包裹起来,并保存在堆里。因此,装箱后的值需要更多的内存,并需要额外的内存搜索来获取被包裹的原始值。
Java 8为我们前面所说的函数式接口带来了一个专门的版本,以便在输入和输出都是原始类型时避免自动装箱的操作。比如,在下面的代码中,使用IntPredicate就避免了对值1000进行装箱操作,但要是用Predicate
IntPredicate evenNumbers = (int i) -> i % 2 == 0;
evenNumbers.test(1000); // 无装箱
Predicate<Integer> oddNumbers = (Integer i) -> i % 2 == 1;
oddNumbers.test(1000); // 有装箱
ps:
1.泛型(比如Consumer
2.IntPredicate没有继承Predicate接口。