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 既 type
係 null
,咁以下使用 Collectors.groupingBy
既方法係 work:
final Map<String, List<Item>> error = items.stream().collect(groupingBy(Item::getType));
但因為有一啲 elements 既 type
係 null
,所以就會有 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);