Java8常用方法,让你的代码更简化
- 一、基本概念
- 二、常用操作
- 1. 获取流
- 2. 筛选filter-筛选年龄大于20岁的集合
- 3. 去重distinct-去掉重复的结果
- 4. 截取-截取流的前N个元素
- 5. 映射-获取list中某一个属性集合
- 6. 合并多个流
- 7. 是否匹配任一元素:anyMatch
- 8. 是否匹配所有元素:allMatch
- 9. 是否未匹配所有元素:noneMatch
- 10. 获取任一元素:findAny-随机取出一个元素
- 11. 获取第一个元素:findFirst
- 12. 归约元素求和
- 13. 将普通流转换成数值流
- 14. 计数
- 15. 求最值
- 16. 求平均值
- 17. 连接字符串
- 18. 自定义规约操作
- 19. 一级分组
- 20. 多级分组(支持在完成一次分组后,分别对每个小组再进行分组)
- 21. 对分组进行统计
- 22. 将收集器的结果转换成另一种类型(很实用)
- 23. 根据id按sex分组统计数据(求和,个数,平均数,最大最小值)
- 24. List转Map(常用方法)
一、基本概念
1. 什么是流?
流可以理解为一种高级集合,我们写代码集合无处不在,有时候处理起来很麻烦,若要对集合进行筛选、投影,需要写大量的代码,
而流是以声明的形式操作集合,它就像SQL语句,我们只需告诉流需要对集合进行什么操作,它就会自动进行操作,并将执行结果交给你,无需我们自己手写代码。
2. 流的特点
只能遍历一次
我们可以把流想象成一条流水线,流水线的源头是我们的数据源(一个集合),数据源中的元素依次被输送到流水线上,我们可以在流水线上对元素进行各种操作。一旦元素走到了流水线的另一头,那么这些元素就被“消费掉了”,我们无法再对这个流进行操作。当然,我们可以从数据源那里再获得一个新的流重新遍历一遍。
采用内部迭代方式
若要对集合进行处理,则需我们手写处理代码,这就叫做外部迭代。而要对流进行处理,我们只需告诉流我们需要什么结果,处理过程由流自行完成,这就称为内部迭代。
3. 流的操作种类
流的操作分为两种,分别为中间操作 和 终端操作。
中间操作
当数据源中的数据上了流水线后,这个过程对数据进行的所有操作都称为“中间操作”。
中间操作仍然会返回一个流对象,因此多个中间操作可以串连起来形成一个流水线。
终端操作
当所有的中间操作完成后,若要将数据从流水线上拿下来,则需要执行终端操作。
终端操作将返回一个执行结果,这就是你想要的数据。
数据源,所有操作都以这两个数据源来演示;
//直接new对象塞到集合中
List<Familay> familayList = Lists.newArrayList(
new Familay(111, "何金荣", "刘静"),
new Familay(111, "何金荣2", "刘静2"),
new Familay(111, "何金荣2", "刘静2")
);
List<String> strList = Lists.newArrayList("张三", "李四", "王五");
List<Integer> intList = Lists.newArrayList(1, 2, 3, 4, 5);
List<String> resultList = Arrays.asList("因为我", "不知道", "下一辈子", "还是否能", "遇见你");
//获取流
Stream<String> stream = resultList.stream();
二、常用操作
1. 获取流
1.1 集合
这种数据源较为常用,通过stream()方法即可获取流对象:
//获取流
Stream<String> stream = resultList.stream();
1.2 数组
通过Arrays类提供的静态函数stream()获取数组的流对象:
String[] nameArr = {"出山", "绿色", "我曾"};
Stream<String> nameStream = Arrays.stream(nameArr);
1.3 值
直接将几个值变成流对象:
Stream<String> oneStream = Stream.of("我", "爱", "运动");
1.4 文件
直接将几个值变成流对象:
//获取流文件
try (Stream<String> fileStream = Files.lines(Paths.get("文件路径名"), Charset.defaultCharset())) {
//可对fileStream做相关处理
} catch (Exception e) {
e.printStackTrace();
}
2. 筛选filter-筛选年龄大于20岁的集合
//筛选年龄大于20岁的集合
List<UserEntity> userList = Lists.newArrayList(
new UserEntity(111, "何金荣", 10000.00, 25),
new UserEntity(222, "张三", 20000.00, 18),
new UserEntity(333, "李四", 30000.00, 32)
);
List<UserEntity> resultUserList = userList.stream().filter(user -> user.getAge() > 20).collect(Collectors.toList());
log.info("筛选年龄大于20岁的集合为:" + resultUserList);
3. 去重distinct-去掉重复的结果
//去重distinct-去掉重复的结果
List<String> duplicateList = Lists.newArrayList("111", "222", "111", "333", "444");
List<String> duplicateResultList = duplicateList.stream().distinct().collect(Collectors.toList());
log.info("去掉重复后的集合为:" + duplicateResultList);
4. 截取-截取流的前N个元素
//截取流的前N个元素
List<UserEntity> cutStreamList = userList .stream().limit(2).collect(Collectors.toList());
log.info("截取流的前N个元数集合未:" + cutStreamList);
5. 映射-获取list中某一个属性集合
//映射-获取list中某一个属性集合
List<String> userNameList = userList.stream().map(UserEntity::getUserName).collect(Collectors.toList());
log.info("获取集合中userName属性的集合为:" + userNameList);
6. 合并多个流
//合并多个流
List<String> dataList = Lists.newArrayList("111", "222", "111", "333", "444");
Stream<Stream<String>> streamStream = dataList.stream().map(line -> line.split(",")).map(Arrays::stream);
log.info("合并多个流:" + streamStream);
7. 是否匹配任一元素:anyMatch
//anyMatch-判断list中userId是否有111
boolean isExist = userList.stream().anyMatch(user -> user.getUserId().equals(111));
log.info("判断list中userId是否有111:" + isExist);
8. 是否匹配所有元素:allMatch
//allMatch-判断userList中年龄是否全部大于30
boolean isExist = userList.stream().allMatch(user -> user.getAge() > 30);
log.info("判断userList中年龄是否全部大于30:" + isExist);
9. 是否未匹配所有元素:noneMatch
//是否未匹配所有元素:noneMatch-判断userList中用户的工资数全部都不少于一万
boolean isMatch = userList.stream().noneMatch(user -> user.getMoney() < 10000.00);
log.info("判断userList中用户的工资是否全部都不少于一万:" + isMatch);
10. 获取任一元素:findAny-随机取出一个元素
//获取任一元素findAny-随机取出一个元素
Optional<UserEntity> anyUser = userList.stream().findAny();
log.info("随机取出一个元数对象:" + anyUser);
11. 获取第一个元素:findFirst
//获取第一个元素findFirst
Optional<UserEntity> firstUser = userList.stream().findFirst();
log.info("获取第一个元素:" + firstUser);
12. 归约元素求和
//使用Integer.sum函数求和
List<Integer> dataList = Lists.newArrayList(100, 200, 300, 400);
Integer sum = dataList.stream().reduce(0, Integer::sum);
log.info("总和为:" + sum);
//计算总金额
BigDecimal sumMoney = userList.stream().map(UserEntity::getMoney).reduce(BigDecimal.ZERO, BigDecimal::add);
log.info("计算总金额为:" + sumMoney);
13. 将普通流转换成数值流
//将普通流转换成数值流
int ageSum = userList.stream().mapToInt(UserEntity::getAge).sum();
log.info("将年龄转为数值流并求和:" + ageSum);
14. 计数
//计数
long count = userList.stream().count();
log.info("计数为:" + count);
15. 求最值
//求最值,找出用户中年龄最小的用户
Optional<UserEntity> minUser = userList.stream().collect(Collectors.minBy(Comparator.comparingInt(UserEntity::getAge)));
log.info("年龄最小的用户为:" + minUser);
16. 求平均值
//求平均值,求所有用户的平均年龄
Double avgAge = userList.stream().collect(Collectors.averagingInt(UserEntity::getAge));
log.info("平均年龄为:" + avgAge);
17. 连接字符串
//连接字符串-将所有人的名字连接成一个字符串
List<String> userNameList = Lists.newArrayList("何金荣", "张三", "李四", "王五");
String userNameStr = userNameList.stream().collect(Collectors.joining(",", "[", "]"));
log.info("连接用户名:" + userNameStr);
String userNameStr2 = userList.stream().map(UserEntity::getUserName).collect(Collectors.joining(",", "[", "]"));
log.info("连接用户名:" + userNameStr2);
18. 自定义规约操作
//自定义规约操作
Integer sumAges = userList.stream().collect(Collectors.reducing(0, UserEntity::getAge, (i, j) -> i + j));
log.info("计算年龄总和为:" + sumAges);
19. 一级分组
//对工资阶段进行分组
Map<String, List<UserEntity>> collect1 = userList.stream().collect(Collectors.groupingBy((user) -> {
if (BigDecimal.valueOf(25000).compareTo(user.getMoney()) < 0) {
return "金领族";
} else if (BigDecimal.valueOf(15000).compareTo(user.getMoney()) < 0) {
return "白领族";
} else {
return "屌丝族";
}
}));
log.info("一级分组:" + collect1);
//名字分组
Map<String, List<UserEntity>> collect2 = userList.stream().collect(Collectors.groupingBy(UserEntity::getUserName));
log.info("名字分组:" + collect2);
20. 多级分组(支持在完成一次分组后,分别对每个小组再进行分组)
//多级分组
Map<String, List<UserEntity>> collect3 = userList.stream().collect(Collectors.groupingBy((user) -> {
if (BigDecimal.valueOf(25000).compareTo(user.getMoney()) < 0) {
return "金领族";
} else if (BigDecimal.valueOf(15000).compareTo(user.getMoney()) < 0) {
return "白领族";
} else {
return "屌丝族";
}
}, Collectors.groupingBy(UserEntity::getUserName)));
log.info("多级分组:" + collect3);
21. 对分组进行统计
//对分组进行统计-统计每一组的人数
Map<String, Long> collect3 = userList.stream().collect(Collectors.groupingBy((user) -> {
if (BigDecimal.valueOf(25000).compareTo(user.getMoney()) < 0) {
return "金领族";
} else if (BigDecimal.valueOf(15000).compareTo(user.getMoney()) < 0) {
return "白领族";
} else {
return "屌丝族";
}
}, Collectors.counting()));
log.info("多级分组:" + collect3);
22. 将收集器的结果转换成另一种类型(很实用)
//根据性别分组并取得年龄最大的一条
Map<Integer, UserEntity> userMap = userList.stream().collect(Collectors.groupingBy(UserEntity::getSex, Collectors.collectingAndThen(
Collectors.maxBy(Comparator.comparingInt(UserEntity::getAge)),
Optional::get)));
log.info("转为Map:" + userMap);
23. 根据id按sex分组统计数据(求和,个数,平均数,最大最小值)
//根据sex分组统计数据(求和,个数,平均数,最大最小值)
Map<Integer, IntSummaryStatistics> collect6 = userList.stream().collect(Collectors.groupingBy(UserEntity::getSex, Collectors.summarizingInt(UserEntity::getAge)));
log.info("根据sex分组求和:" + collect6);
24. List转Map(常用方法)
/**
* List转Map-经常用
* 注意:
* toMap 如果集合对象中有重复的key,则会报错Duplicate Key...
* 可以用(key1, key2) -> key1来设置,如果有重复的key,则保留key1,舍弃Key2
*/
Map<Integer, UserEntity> collect7 = userList.stream().collect(Collectors.toMap(UserEntity::getUserId, user -> user, (key1, key2) -> key1));
log.info("List转Map:" + collect7);