Java8中提供了3大类函数式接口:Predicate、Consumer和Function。
这三大类函数式接口基本覆盖了我们开发中大多数需要使用lambda的场景,不需要我们再自己定义函数式接口了,也就是说我们第二节的例子中定义的函数式接口AppleFormatter,是可以不用定义的。
@FunctionalInterface
public interface AppleFormatter {
String accept(Apple apple);
}
我们下面就来看一下这三种函数式接口。
Predicate
提供一个test方法,方法入参为泛型T,返回布尔类型,也就是这个方法可以用来做逻辑判断。
@FunctionalInterface
public interface Predicate<T> {
/**
* Evaluates this predicate on the given argument.
*
* @param t the input argument
* @return {@code true} if the input argument matches the predicate,
* otherwise {@code false}
*/
boolean test(T t);
}
使用Predicate对第二节的例子进行改造。
import java.util.ArrayList;
import java.util.List;
import java.util.function.Predicate;
/**
* @Auther: www.itzhimei.com
* @Description: Predicate
*/
public class Lambda3_3 {
public static void main(String[] args) {
List<Apple> apples = new ArrayList<>();
Apple a1 = new Apple("红",155);
Apple a2 = new Apple("绿",136);
Apple a3 = new Apple("红",169);
apples.add(a1);
apples.add(a2);
apples.add(a3);
Predicate<Apple> gr150 = (Apple a) -> a.getWeight() > 150;
printApple(apples, gr150,"是否是大于150g的苹果:");
Predicate<Apple> eq155 = (Apple a) -> a.getWeight() == 155;
printApple(apples, eq155, "是否等于155g的苹果:");
}
public static void printApple(List<Apple> apples, Predicate<Apple> af, String info) {
for(Apple a : apples) {
System.out.println(info + af.test(a));
}
}
}
输出结果:
是否是大于150g的苹果:true
是否是大于150g的苹果:false
是否是大于150g的苹果:true
是否等于155g的苹果:true
是否等于155g的苹果:false
是否等于155g的苹果:false
Consumer
提供一个accept方法,方法参数为泛型T,返回void,这个方法是做逻辑处理并不会返回任何结果。
@FunctionalInterface
public interface Consumer<T> {
/**
* Performs this operation on the given argument.
*
* @param t the input argument
*/
void accept(T t);
}
import java.util.ArrayList;
import java.util.List;
import java.util.function.Consumer;
import java.util.function.Predicate;
/**
* @Auther: www.itzhimei.com
* @Description: Consumer
*/
public class Lambda3_3_Consumer {
public static void main(String[] args) {
List<Apple> apples = new ArrayList<>();
Apple a1 = new Apple("红",155);
Apple a2 = new Apple("绿",136);
Apple a3 = new Apple("红",169);
apples.add(a1);
apples.add(a2);
apples.add(a3);
Consumer<Apple> printGr150 = (Apple a) -> System.out.println(a.getWeight() > 150?"重苹果":"轻苹果");
printApple(apples, printGr150);
}
public static void printApple(List<Apple> apples, Consumer<Apple> af) {
for(Apple a : apples) {
af.accept(a);
}
}
}
输出结果:
重苹果
轻苹果
重苹果
Function
提供一个apply方法,apply方法入参为泛型T,返回为泛型R,这个方法即支持传入参数,也支持返回值,兼具了Predicate和Consumer的特性,而且方法更灵活。
@FunctionalInterface
public interface Function<T, R> {
/**
* Applies this function to the given argument.
*
* @param t the function argument
* @return the function result
*/
R apply(T t);
}
import java.util.ArrayList;
import java.util.List;
import java.util.function.Consumer;
import java.util.function.Function;
/**
* @Auther: www.itzhimei.com
* @Description: Function
*/
public class Lambda3_3_Function {
public static void main(String[] args) {
List<Apple> apples = new ArrayList<>();
Apple a1 = new Apple("红",155);
Apple a2 = new Apple("绿",136);
Apple a3 = new Apple("红",169);
apples.add(a1);
apples.add(a2);
apples.add(a3);
Function<Apple, String> printWL = (Apple a) -> a.getWeight() > 150?"重苹果":"轻苹果";
printApple(apples, printWL);
}
public static void printApple(List<Apple> apples, Function<Apple, String> af) {
for(Apple a : apples) {
System.out.println(af.apply(a));
}
}
}
输出结果:
重苹果
轻苹果
重苹果
以上三种函数式接口,还提供了非常多的原始类型的接口:IntPredicate、IntConsumer、IntFunction<R>、LongPredicate、LongConsumer、LongFunction<R>等等。
提供这些类的目的就是避免装箱拆箱,因为Predicate<T>如果是int作为参数,则要用int的对象类型Integer,因为原始类型不支持泛型使用,所以要使用Integer,这时就设计到装箱和拆箱,这有性能上的影响,所以java为开发者提供了多种原始类型的的函数式接口,避免装箱和拆箱。