这一节学一下用得比较多的三个函数式接口:--Predicate--Consumer--Function
java.util.function.Predicate接口定义了一个名叫test的抽象方法,它接受泛型T对象,并返回一个boolean。代码:
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);剩余两个函数就不一一举例了。
java.util.function.Consumer定义了一个名叫accept的抽象方法,它接受泛型T的对象,没有返回(void)。
java.util.function.Function<T, R>接口定义了一个叫作apply的方法,它接受一个泛型T的对象,并返回一个泛型R的对象。
拓展: 原始类型特化 在Java里有一个将原始类型转换为对应的引用类型的机制。这个机制叫作装箱(boxing)。相反的操作,也就是将引用类型转换为对应的原始类型,叫作拆箱(unboxing)
装箱后的值本质上就是把原始类型包裹起来,并保存在堆里。因此,装箱后的值需要更多的内存,并需要额外的内存搜索来获取被包裹的原始值。
Java 8为我们前面所说的函数式接口带来了一个专门的版本,以便在输入和输出都是原始类型时避免自动装箱的操作。比如,在下面的代码中,使用IntPredicate就避免了对值1000进行装箱操作,但要是用Predicate就会把参数1000装箱到一个Integer对象中:
IntPredicate evenNumbers = (int i) -> i % 2 == 0; evenNumbers.test(1000); // 无装箱 Predicate<Integer> oddNumbers = (Integer i) -> i % 2 == 1; oddNumbers.test(1000); // 有装箱ps: 1.泛型(比如Consumer中的T)只能绑定到引用类型。这是由泛型内部的实现方式造成的。 2.IntPredicate没有继承Predicate接口。
转载于:https://www.cnblogs.com/pain-first/p/11477104.html