这篇文章我们聊聊Stream的一些进阶的操作api,准备数据这些与上篇相同,这里就不阐述,如果不了解的,欢迎大家先看
玩转Java 8 Stream系列一
这篇文章还是通过对比的方式进行。
写法一
Map> familyMap = new HashMap(); for (Member member : memberList) { //操作Member对象 List members = familyMap.get(member.getFamilyId()); if (CollectionUtils.isEmpty(members)) { members = new ArrayList<>(); } members.add(member.getMemberName()); familyMap.put(member.getFamilyId(), members); }
解析:遍历集合,根据familyId查询map,如果不存在,则实例化一个集合,将成员名字添加进去
写法二
familyMap = memberList.stream().collect(Collectors.groupingBy(Member::getFamilyId, Collectors.mapping(Member::getMemberName, Collectors.toList())));
解析:通过stream的写法,写法上无需判断集合以及创建集合,这里是先按照familyId进行分组(Collectors.groupingBy),再处理分组后List集合,使用Collectors.mapping方法,获取成员名称,最后再选择输出的形式,这里使用Collectors.toList(),最后输出Map
分析:先将数据以家庭ID分组后,在将分组后的成员积蓄累加,写法与上面的查询以每个家庭为组内的成员名称集合类似,只不过这里要对数据中totalMoney进行累加
写法一
MapfamilyMap = new HashMap(); for (Member member : memberList) { //操作Member对象 BigDecimal bigDecimal = familyMap.get(member.getFamilyId()); if (Objects.isNull(bigDecimal)) { bigDecimal = new BigDecimal(0); } bigDecimal= bigDecimal.add(member.getTotalMoney()); familyMap.put(member.getFamilyId(), bigDecimal); }
写法二
familyMap = collect(Collectors.groupingBy(Member::getFamilyId, Collectors.reducing(BigDecimal.ZERO, Member::getTotalMoney, BigDecimal::add)));
写法一
MapfamilyMap = new HashMap(); for (Member member : memberList) { //操作Member对象 Integer memberTotal = familyMap.get(member.getFamilyId()); if (Objects.isNull(memberTotal)) { memberTotal = 0; } memberTotal += member.getMemberAmount(); familyMap.put(member.getFamilyId(), memberTotal); }
写法二
familyMap = memberList.stream().collect(Collectors.groupingBy(Member::getFamilyId, Collectors.reducing(0, Member::getMemberAmount, Integer::sum)));
假如我们要统计每个家庭的数量之和、数量平均值、最大值、最小值,这些,那么使用写法会比较麻烦,要对 familyMap 集合再做比较
那么通过下面的写法可以避免这些问题
Mapcollect = memberList.stream().collect(Collectors.groupingBy(Member::getFamilyId, Collectors.summarizingInt(Member::getMemberAmount)));
生成一个value为 IntSummaryStatistics对象,如果我们想统计累加
Mapcollect2 = collect.entrySet().stream().collect(Collectors.toMap(Map.Entry::getKey, k -> k.getValue().getSum()));
如果想统计最大值,只需要将 getSum方法修改成getMax,最小值修改成getMin ,求和 getCount
平均值getAverage 是不是比较方便
写法一
boolean isExist = false; for (Member member : memberList) { //操作Member对象 if ("张三".equals(member.getMemberName())){ isExist = true; break; } } System.out.println(isExist);
写法二
Optionalfirst = memberList.stream().filter(k -> "张三".equals(k.getMemberName())).findFirst(); System.out.println(first.isPresent());
如果找到第一个,那么就返回一个 Optional对象,调用isPresent方法,查看是否存在,而且返回的Optional对象还可以进行下一步操作,例如再次过滤,调用filter方法。
例如通过map,我们获取成员名称,那么他会将成员名字作为一个整体返回,不会在细分,而flatMap会将成员名称再细分,假如成员名称叫张三-1,map会将张三-1作为一个整体来处理,flatMap则将张三-1会再次拆分处理,可能拆分成张、三、-、1这种。而在使用上的区别是flatMap的入参必须是Stream类型,而map则无需,例如下面代码
memberList.stream().flatMap(k -> Stream.of(k.getMemberName().split("-"))).collect(Collectors.toList()).forEach(System.out::println);
flatMap入参是Stream类型,所以我们可以对memberName字段进行处理,例如上面是通过-来分割,将分割后的结果加入的Stream中,因为是Sream类型,所以还可以对结果进行其他的逻辑处理。
memberList.stream().map(Member::getMemberName).collect(Collectors.toList()).forEach(System.out::println);
map无需Steam类型,处理更加简单。