➜ Old React website
Chung Cheuk Hang MichaelJava Web Developer
Spring 基礎功能:AOPCharles 代理伺服器

Java 8:Group 起一個 List<Item>

Table of contents

1 情境

我地有一個咁既自定義 class Item
1@Data 2@Accessors(chain = true) 3@FieldDefaults(level = PRIVATE) 4class Item { 5 String name; 6 String type; 7}
如果我地有一個 List<Item>,而我地想將相同 type 既 elements group 起,成為一個 Map<String, List<Item>>,咁可以點做?
1final List<Item> items = asList( 2 new Item().setName("One").setType("1"), 3 new Item().setName("Two").setType("1"), 4 new Item().setName("Three").setType("1"), 5 new Item().setName("Four").setType("2"), 6 new Item().setName("Same").setType(null), 7 new Item().setName("Same").setType(null), 8 new Item().setName(null).setType(null) 9);
期望結果:
1{ 2 "1": [ 3 { "name": "One", "type": "1" }, 4 { "name": "Two", "type": "1" }, 5 { "name": "Three", "type": "1" } 6 ], 7 "2": [ 8 { "name": "Four", "type": "2" }, 9 ], 10 null: [ 11 { "name": "Same", "type": null }, 12 { "name": "Same", "type": null }, 13 { "name": null, "type": null } 14 ] 15}

2 解決方法

2.1 Collectors#groupingBy(要小心 null

如果 List<Item> items 裡面冇一個 element 既 typenull,咁以下使用 Collectors.groupingBy 既方法係 work:
final Map<String, List<Item>> error = items.stream().collect(groupingBy(Item::getType));
但因為有一啲 elements 既 typenull,所以就會有 exception:
Exception in thread "main" java.lang.NullPointerException: element cannot be mapped to a null key at java.util.Objects.requireNonNull(Objects.java:228) at java.util.stream.Collectors.lambda$groupingBy$45(Collectors.java:907)
參考資料:

2.2 Stream#collect(Supplier, BiConsumer, BiConsumer)

要 handle 到 null key,就要用 Stream#collect(Supplier<R>, BiConsumer<R, ? super T>, BiConsumer<R, R>) 而唔係一般既 Stream#collect(Collector<? super T, A, R>)
1final Map<String, List<Item>> grouped = items 2 .stream() 3 .collect(HashMap::new, 4 (m, v) -> m.merge(v.getType(), 5 asList(v), 6 (oldList, newList) -> Stream.concat(oldList.stream(), 7 newList.stream()) 8 .collect(toList())), 9 HashMap::putAll);