JDK1.8 Stream之toMap和groupingBy全参数的使用

Posted caizhiqin

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了JDK1.8 Stream之toMap和groupingBy全参数的使用相关的知识,希望对你有一定的参考价值。

现在有一个商品地址对象的集合List<ProductAddress> productAddresses,该集合中productId和addressId是一对多的关系

 1 @Data
 2 @AllArgsConstructor
 3 class ProductAddress {
 4     private int productId;
 5 
 6     private int addressId;
 7 
 8     private static List<ProductAddress> productAddresses = new ArrayList<>();
 9 
10     static {
11         productAddresses.add(new ProductAddress(1001, 1));
12         productAddresses.add(new ProductAddress(1001, 2));
13         productAddresses.add(new ProductAddress(1001, 3));
14         productAddresses.add(new ProductAddress(1002, 3));
15         productAddresses.add(new ProductAddress(1002, 4));
16         productAddresses.add(new ProductAddress(1003, 5));
17     }
18 }

需求

以productId分组变成一个Map<Integer,List<ProductAddress>>

传统方法

 1 public static void main(String[] args) {
 2     Map<Integer, List<ProductAddress>> map = new HashMap<>();
 3     for (ProductAddress productAddress : productAddresses) {
 4         if (map.get(productAddress.getProductId()) == null) {
 5             map.put(productAddress.getProductId(), new ArrayList<>(Arrays.asList(productAddress)));
 6         } else {
 7             map.get(productAddress.getProductId()).add(productAddress);
 8         }
 9     }
10     System.out.println(JSONObject.toJSON(map));
11 }

lambda表达式实现

1 public static void main(String[] args) {
2     Map<Integer, List<ProductAddress>> map = productAddresses.stream().collect(Collectors.groupingBy(ProductAddress::getProductId));
3     System.out.println(JSONObject.toJSON(map));
4 }

新的需求

以productId分组变成一个Map<Integer,List<Integer>>,value是其对应的addressId的集合

传统方法

 1 public static void main(String[] args) {
 2     Map<Integer, List<Integer>> map = new HashMap<>();
 3     for (ProductAddress productAddress : productAddresses) {
 4         if (map.get(productAddress.getProductId()) == null) {
 5             map.put(productAddress.getProductId(), new ArrayList<>(Arrays.asList(productAddress.getAddressId())));
 6         } else {
 7             map.get(productAddress.getProductId()).add(productAddress.getAddressId());
 8         }
 9     }
10     System.out.println(JSONObject.toJSON(map));
11 }

lambda表达式实现

首先想到的是使用toMap把value转成list并使用toMap提供的key冲突解决办法。

 1 public static void main(String[] args) {
 2     Map<Integer, List<Integer>> map = productAddresses.stream()
 3             .collect(Collectors.groupingBy(ProductAddress::getProductId, HashMap::new,
 4                     Collectors.mapping(ProductAddress::getAddressId, Collectors.toList())));
 5     productAddresses.stream().collect(Collectors.toMap(ProductAddress::getProductId, v -> new ArrayList(Arrays.asList(v.getAddressId())), (existValue, newValue) -> {
 6         existValue.addAll(newValue);
 7         return existValue;
 8     }));
 9     System.out.println(map);
10 }

但感觉这个写法看起来怪怪的,琢磨groupingBy发现,使用groupingBy的后两个参数完成对象到具体字段的映射可以优雅实现

1 public static void main(String[] args) {
2     Map<Integer, List<Integer>> map = productAddresses.stream()
3             .collect(Collectors.groupingBy(ProductAddress::getProductId, HashMap::new,
4                     Collectors.mapping(ProductAddress::getAddressId, Collectors.toList())));
5     System.out.println(map);
6 } 

以上是关于JDK1.8 Stream之toMap和groupingBy全参数的使用的主要内容,如果未能解决你的问题,请参考以下文章

Java基础之Stream流(JDK1.8新特性)

stream中查库,属于循环查库吗

深入理解Stream之原理剖析

深入理解Stream之foreach源码解析

Java8新特性Stream之list转map及问题解决

Java stream操作toMap总结