×

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

我的笔记 我的笔记 发表于2018-08-07 19:49:04 浏览2420 评论0

抢沙发发表评论

现在有一个商品地址对象的集合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;
 9 
10     static {
11         productAddresses = new ArrayList<>();
12         productAddresses.add(new ProductAddress(1001, 1));
13         productAddresses.add(new ProductAddress(1001, 2));
14         productAddresses.add(new ProductAddress(1001, 3));
15         productAddresses.add(new ProductAddress(1002, 3));
16         productAddresses.add(new ProductAddress(1002, 4));
17         productAddresses.add(new ProductAddress(1003, 5));
18     }
19 }

需求

以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 } 
我的笔记博客版权我的笔记博客版权