Java8 各种集合的 Stream 操作示例

5,683 阅读3分钟

前言

本篇文章是个笔记篇......其实专门是写给同事的,他说他不会用 Java8 之后的 lambda 操作,这 Java18 都出来了,你 Java8 还没玩熟,这真是狗听了都摇摇头啊

吐槽

不愿意接触新事物的人,你怎么科普他都不会愿意去学~~ 函数接口、泛型、断言(Predicate)、消费(Consumer)、提供(Supplier)等等,所以我也不说原理了,直接写代码示例吧。。。需要的时候直接复制粘贴,实体类名改掉就 OK。

给定一个实体类

@Data
public class ReviewerRest {
  private Long id;
  private Long reviewerId;
  private Bigdecimal price;
  private LocalDate date;
  private Integer rest;
}

将对象集合转成对象中某个属性的集合

List<ReviewerRest> list = new ArrayList<>();
List<Long> ids = list.stream().map(ReviewerRest::getId).collect(Collectors.toList());

将某个属性的集合转成对象集合

List<Long> ids = new ArrayList<>();

List<ReviewerRest> list = ids.stream().map(id -> {
  ReviewerRest rest = new ReviewerRest();
  rest.setRest(1);
  rest.setDate(LocalDate.now());
  rest.setReviewerId(1000L);
  return rest;
}).collect(Collectors.toList());

判断集合中是否有一个对象包含某个属性

boolean exist = list.stream().anyMatch(rest -> rest.getReviewerId().equals(1000L));
//...... allMatch 和 anyMatch 类似

对集合中某个对象的属性求和

BigDecimal reduce = list.stream().map(ReviewerRest::getPrice).reduce(BigDecimal.ZERO, BigDecimal::add);

集合转 Map (普通)

Map<Long, ReviewerRest> map = list.stream().collect(Collectors.toMap(ReviewerRest::getId, x -> x));

集合转 Map (key 存在重复)

当集合中 id 会存在重复时,上面那种方式会报错,此时需要指定重复时选用哪一个 value

Map<Long, ReviewerRest> map = list.stream().collect(Collectors.toMap(ReviewerRest::getId, x -> x, (before, after) -> after));

集合转 Map (value 存在 null 值)

当 value 存在 null 值时上面那种方式会报错,此时需要换一种写法

Map<Long, LocalDate> map = list.stream().collect(HashMap::new, (mapItem, item) -> mapItem.put(item.getId(), item.getDate()), HashMap::putAll);

集合分组 转 Map

Map<Long, List<ReviewerRest>> map = list.stream().collect(Collectors.groupingBy(ReviewerRest::getId));

集合分组 转 Map 进阶

有时候分组之后还要对某个属性二次操作聚合出我们希望的结果,这个时候可以使用 Collectors.collectingAndThen。

例如下面的

    OfflineRepay o1 = new OfflineRepay();  
    o1.setOrderNo("TQYJKN20230709121074922");  
    o1.setRepayNum("1,2,3");  
    OfflineRepay o2 = new OfflineRepay();  
    o2.setOrderNo("TQYJKN20230709121074922");  
    o2.setRepayNum("4");  
    OfflineRepay o3 = new OfflineRepay();  
    o3.setOrderNo("TQYJKN20230709121074922");  
    o3.setRepayNum("5");  

    OfflineRepay o4 = new OfflineRepay();  
    o4.setOrderNo("TQYJKN20230709121074921");  
    o4.setRepayNum("1,2");  
    OfflineRepay o5 = new OfflineRepay();  
    o5.setOrderNo("TQYJKN20230709121074921");  
    o5.setRepayNum("4");  
    OfflineRepay o6 = new OfflineRepay();  
    o6.setOrderNo("TQYJKN20230709121074921");  
    o6.setRepayNum("5");

例如上面的数据,我们希望以 orderNo 分组之后,再 split repayNum 然后转换成 Map<orderNo,List>

 List<OfflineRepay> list;
 
 Map<String, List<Integer>> collect = list.stream().collect(Collectors.groupingBy(OfflineRepay::getOrderNo,  
Collectors.collectingAndThen(Collectors.mapping(OfflineRepay::getRepayNum,Collectors.joining(",")),  
item -> Arrays.stream(item.split(",")).map(Integer::parseInt).collect(Collectors.toList()))  
));

集合分区 转 Map

Map<Boolean, List<ReviewerRest>> map = list.stream().collect(Collectors.partitioningBy(r -> r.getRest() == 1));

集合分组个数统计

Map<Long, Long> map = list.stream().collect(Collectors.groupingBy(ReviewerRest::getId,Collectors.counting()));

集合分组转某个属性集合

Map<Long, List<Integer>> map = list.stream().collect(Collectors.groupingBy(ReviewerRest::getId,Collectors.mapping(ReviewerRest::getRest,Collectors.toList())));

集合分组聚合查询最大元素

Map<Long, Optional<ReviewerRest>> map = list.stream().collect(Collectors.groupingBy(ReviewerRest::getReviewerId, Collectors.maxBy(Comparator.comparing(ReviewerRest::getDate))));

集合分组聚合求和

//目前只支持 int、double、long
Map<Long, Long> map = list.stream().collect(Collectors.groupingBy(ReviewerRest::getReviewerId, Collectors.summingLong(ReviewerRest::getRest)));

flatMap 获取嵌套集合最小值

给定一个数据结构

image.png

要获取最内层 billList 最小的截止日期可以使用 flatMap

LocalDate min = loanList.stream().flatMap(loan -> loan.getBillList().stream())
    .map(CallStrategyPlanDetail.Bill::getDueDate)
    .min(LocalDate::compareTo)
    .orElseThrow();

结语

这篇文章没什么好说的,也不算一篇文章,做个笔记吧。。。以后有用到的话直接过来 copy ......暂时只想起来这么多,后续用到其他再来更新~~

如果这篇文章对你有帮助,记得点赞加关注!你的支持就是我继续创作的动力!