开启掘金成长之旅!这是我参与「掘金日新计划 · 12 月更文挑战」的第10天,点击查看活动详情
本文主要介绍四大函数式接口及Stream流相关知识,你如果还不懂Stream及函数式接口的,就快来看快来学...
12. 四大函数式接口
函数式接口:只有一个方法的接口。接口上面会有
@FunctionalInterface注解。
四大函数式接口:Consumer、Function、Predicate、Supplier。
Function函数式接口
只要是函数型接口,都能用lambda表达式进行简化。
Function函数型接口,有一个输入参数,有一个输出。
下面这个示例的功能就是输入什么返回什么。
public static void main(String[] args) {
//就写了个工具类
Function function = new Function<String,String>() {
@Override
public String apply(String str) {
return str;
}
};
}
lambda简化:
public static void main(String[] args) {
Function<String,String> function = (str)->{
return str;
};
System.out.println(function.apply("asd"));//结果输出asd
}
Predicate函数型接口,这是一个断定型的函数式接口,有一个输入参数,返回值只能是布尔值。
当然下面这个也是可以用lambda简化的。
public static void main(String[] args) {
//判断字符串是否为空
Predicate<String> predicate = new Predicate<String>() {
@Override
public boolean test(String str) {
return str.isEmpty();
}
};
System.out.println(predicate.test(""));//结果输出true
}
Consumer消费型函数式接口,只有输入没有返回值。其中foreach传入的就是这个消费型函数式接口。
public static void main(String[] args) {
Consumer<String> consumer = new Consumer<String>() {
@Override
public void accept(String str) {
System.out.println(str);
}
};
//打印字符串
consumer.accept("adasda");//结果输出adasda
}
Supplier供给型函数式接口,没有参数只有返回值。
public static void main(String[] args) {
//lambda简化
Supplier<Integer> supplier = ()->{
System.out.println("get()");
return 1024;
};
System.out.println(supplier.get());//结果输出get() 1024
}
这就是四大函数式接口。再次强调:只要是函数式接口都可以用lambda表达式来简化。
13. Stream流式计算
什么是Stream流式计算
大数据包含存储+计算。像集合、MySQL这些本质都是用来存储的东西,计算是要交给流来操作的。
list转stream流:list.stream()
- filter:过滤,就是过滤器,符合条件的通过,不符合条件的过滤掉
// 筛选出成绩不为空的学生人数
count = list.stream().filter(p -> null != p.getScore()).count();
- map:映射,他将原集合映射成为新的集合,在VO、PO处理的过程中较常见。
// 取出所有学生的成绩
List<Double> scoreList = list.stream().map(p -> p.getScore()).collect(Collectors.toList());
// 将学生姓名集合串成字符串,用逗号分隔
String nameString = list.stream().map(p -> p.getName()).collect(Collectors.joining(","));
- sorted:排序,可以根据指定的字段进行排序
// 按学生成绩逆序排序 正序则不需要加.reversed()
filterList = list.stream().filter(p -> null != p.getScore()).sorted(Comparator.comparing(UserPo::getScore).reversed()).collect(Collectors.toList());
- forEach: 这个应该是最常用的,也就是为每一个元素进行自定义操作
- collect:聚合,可以用于GroudBy按指定字段分类,也可以用于返回列表或者拼凑字符串
// 返回list
List<Double> scoreList = list.stream().map(p -> p.getScore()).collect(Collectors.toList());
// 返回string用逗号分隔
String nameString = list.stream().map(p -> p.getName()).collect(Collectors.joining(","));
- statistics:统计,可以统计中位数,平均值,最大最小值
DoubleSummaryStatistics statistics = filterList.stream().mapToDouble(p -> p.getScore()).summaryStatistics();
System.out.println("列表中最大的数 : " + statistics.getMax());
System.out.println("列表中最小的数 : " + statistics.getMin());
System.out.println("所有数之和 : " + statistics.getSum());
System.out.println("平均数 : " + statistics.getAverage());
- parallelStream:并行流,可以利用多线程进行流的操作,提升效率。但是其不具备线程传播性,因此使用时需要充分评估是否需要用并行流操作
// 并行流
count = list.parallelStream().filter(p -> null != p.getScore()).count();
下面看案例与要求:
/**
* 题目要求:一分钟内完成此题,只能用一行代码实现!
* 现在有五个用户!筛选:
* 1、ID必须是偶数
* 2、年龄必须大于23
* 3、用户名转为大写字母
* 4、用户名字母倒着排序
* 5、只输出一个用户!
*/
public class Test {
public static void main(String[] args) {
User u1 = new User(1,"a",21);
User u2 = new User(2,"b",22);
User u3 = new User(3,"c",23);
User u4 = new User(4,"d",24);
User u5 = new User(6,"e",25);
//集合就是存储
List<User> list = Arrays.asList(u1, u2, u3, u4, u5);
//计算交给stream流
//链式编程
list.stream()
.filter((u)->{return u.getId()%2==0;})
.filter(u->{return u.getAge() > 23;})
.map(u->{return u.getName().toUpperCase();})
.sorted((uu1,uu2)->{return uu2.compareTo(uu1);})
.limit(1)
.forEach(System.out::println);
}
}