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; 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 }