目前我们常用的函数式接口主要有:
BiConsumer<T,U>:代表了一个接受两个输入参数的操作,并且不返回任何结果
BiFunction<T,U,R>:代表了一个接受两个输入参数的方法,并且返回一个结果
BinaryOperator:代表了一个作用于于两个同类型操作符的操作,并且返回了操作符同类型的结果
BiPredicate<T,U>:代表了一个两个参数的boolean值方法
BooleanSupplier:代表了boolean值结果的提供方
Consumer:代表了接受一个输入参数并且无返回的操作
Function<T,R>:接受一个输入参数,返回一个结果。
Predicate:接受一个输入参数,返回一个布尔值结果。
Supplier:无参数,返回一个结果。
java.lang.Runnable
java.util.concurrent.Callable
java.util.Comparator
除了几个 java8 前就有的复合函数式接口定义的接口,函数式接口大都定义在 java.utils.function 包下
Predicate<T>函数
断言函数(布尔值函数),核心方法是test(),返回一个Boolean类型的值,用来判断。一般配合stream的filter使用。
public static void main(String[] args) {
// lambda实现
Predicate<Integer> predicate1 = t -> t > 10;
// 匿名内部类实现
Predicate<Integer> predicate2 = new Predicate<Integer>() {
@Override
public boolean test(Integer t) {
return t < 20;
}
};
// 配合stream的filter使用,filter会执行predicate的test方法,然后过滤掉返回结果为false的数值
List<Integer> collect1 = Lists.newArrayList(1, 11, 22).stream().filter(predicate1).collect(Collectors.toList());
System.out.println(collect1);// [11, 22]
// and()方法,逻辑与操作
List<Integer> collect2 = Lists.newArrayList(1, 11, 22).stream().filter(predicate1.and(predicate2)).collect(Collectors.toList());
System.out.println(collect2);// [11]
// or()方法,逻辑或操作
List<Integer> collect3 = Lists.newArrayList(1, 11, 22).stream().filter(predicate1.or(predicate2)).collect(Collectors.toList());
System.out.println(collect3);// [1, 11, 22]
// negate()方法,test结果取反
System.out.println(predicate1.negate().test(1));// true
// isEqual()方法,调用object的equals方法,会先判断object是否为null,不需要自己判断了,避免NPE。
System.out.println(Predicate.isEqual(null).test(null));//true
System.out.println(Predicate.isEqual(null).test("str"));//false
System.out.println(Predicate.isEqual("str").test(null));//false
}
Function<T,R>函数
映射处理函数,核心方法是apply(),接受一个T类型处理成返回值R类型。
public static void main(String[] args) {
// lambada实现
Function<Integer, String> function = integer -> integer + "1";
// 匿名内部类实现
Function<Integer, String> function1 = new Function<Integer, String>() {
@Override
public String apply(Integer integer) {
return integer + "1";
}
};
// 配合stream的map使用,map会执行function的apply方法,获取返回结果
List<String> collect1 = Lists.newArrayList(1, 2, 3).stream().map(function).collect(Collectors.toList());
System.out.println(collect1);//[11, 21, 31]
/*
* compose()方法,调用R apply(T)方法之前对T类型入参做处理
* andThen()方法,调用R apply(T)方法之后对R类型返回值做处理
*/
// (x+20)*10+10
Function<Integer, Integer> function2 = (x -> x * 10);
function2 = function2.compose(x -> x + 20);
function2 = function2.andThen(x -> x + 10);
System.out.println(function2.apply(8));//290
// identity()方法,返回入参本身,不做处理。注意防止Duplicate key异常
Stream<String> stream = Stream.of("This", "is", "a", "test", "test");
Map<String, Integer> lengthMap = stream.collect(Collectors.toMap(Function.identity(), String::length, (v1, v2) -> v2));
System.out.println(lengthMap);//{a=1, test=4, This=4, is=2}
ArrayList<Order> orderList = Lists.newArrayList(new Order("000001", "苹果订单"), new Order("000001", "微软订单"));
Map<String, Order> orderMap = orderList.stream().collect(Collectors.toMap(Order::getOrderNo, Function.identity(), (v1, v2) -> v2));
System.out.println(orderMap);//{000001=Test3.Order(orderNo=000001, name=微软订单)}
}
@Data
@NoArgsConstructor
@AllArgsConstructor
private static class Order {
private String orderNo;
private String name;
}
Comparator<T>函数
比较器函数,核心方法是compare(T o1, T o2);
public static void main(String[] args) {
// lambda实现
//Comparator<Integer> comparator = (o1, o2) -> o1 - o2;
Comparator<Integer> comparator = Comparator.comparingInt(o -> o);
// 匿名内部类实现
Comparator<Integer> comparator1 = new Comparator<Integer>() {
@Override
public int compare(Integer o1, Integer o2) {
return o1 - o2;
}
};
// 使用
ArrayList<Integer> list = Lists.newArrayList(11, 22, 3, 6);
list.sort(comparator);
System.out.println(list);//[3, 6, 11, 22]
// reversed()方法,逆转排序
list.sort( comparator.reversed());
System.out.println(list);//[22, 11, 6, 3]
/* thenComparing()方法,一次排序相等时进行二次排序 */
// 姓名长度比较函数
//Comparator<User> comparatorName = (o1, o2) -> o1.getName().length() - o2.getName().length();
Comparator<User> comparatorName = Comparator.comparingInt(o -> o.getName().length());
// 年龄比较函数
Comparator<User> comparatorAge = (o1, o2) -> o1.getAge() - o2.getAge();
ArrayList<User> users = Lists.newArrayList(
new User("zhangsan", 20),
new User("lisi", 27),
new User("wangwu", 21),
new User("yuyu", 26));
users.sort(comparatorName);
System.out.println("按照姓名长度排序" + users);
users.sort(comparatorName.thenComparing(comparatorAge));
System.out.println("按照姓名长度排序然后按照年龄排序" + users);
}
@Data
@NoArgsConstructor
@AllArgsConstructor
static class User{
private String name;
private Integer age;
}
map/peek/forEach区别:
map:能处理任何类型元素,因其参数类型Function的功能方法是R apply(T t),处理输入参数T并返回结果R
peek:只能处理非String类引用类型元素,因其参数类型Consumer的功能方法是void accept(T t),处理输入参数T但不返回处理结果
forEach:处理元素但不返回流,会中断流操作