sbf123中文线路
  咨询电话:13973376576

sbf888官方导航

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 ProductAddress1));13 productAddresses.add(new ProductAddress2));14 productAddresses.add(new ProductAddress3));15 productAddresses.add(new ProductAddress3));16 productAddresses.add(new ProductAddress4));17 productAddresses.add(new ProductAddress5));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 }