将 List<Object> 转换为 Map<String, List<Object>> 并根据 List 元素的某些属性区分重复项?

Convert a List<Object> to a Map<String, List<Object>> and distinct the duplicates according to some properties of List's element?

例如,对于两个 类 这样的:

Class RawItem {
    private String category;
    private int code;
    private String name;
}

Class Item {
    private int code;
    private String name;
}

RawItem 列表如下:

[ { "category":"a", "code":1, "name":"item1" }, { "category":"a", "code":1, "name":"item1" }, { "category":"a", "code":2, "name":"item2" }, { "category":"b", "code":1, "name":"item1" }, { "category":"b", "code":1, "name":"item1" } ]

把它变成这样的 Map<String, List<Item>>

{
   "a":[
      {
         "code":1,
         "name":"item1"
      },
      {
         "code":2,
         "name":"item2"
      }
   ],
   "b":[
      {
         "code":1,
         "name":"item1"
      }
   ]
}

任何答复将不胜感激。谢谢。

以下 groupingBy 应该有效。 作为您附加要求的一部分,我们知道无法使用 RawItem 对象的 equals 方法,这就是我们使用过滤器而不是 Stream distinct 方法的原因(*):

    Set<Object> seen = ConcurrentHashMap.newKeySet();

    Map<String, List<Item>> m = 
       l.stream()
        .filter(item -> seen.add(item.category + ":" + item.name + ":" + item.code))
        .collect(Collectors.groupingBy(item -> item.category,
            Collectors.mapping(item -> new Item(item.code, item.name), 
                               Collectors.toList())));

请注意,为了让方法 distinct 起作用并删除重复项,您需要正确实施 [=15] 中的 hashCodeequals 方法=] class.

例如下面的测试:

List<RawItem> list = Arrays.asList(new RawItem("a", 1, "dfg"),
                                   new RawItem("a", 1, "dfg"),
                                   new RawItem("a", 1, "fdgdfdfgdg"),
                                   new RawItem("b", 1, "dfg"));

Map<String, List<Item>> map = // the above

System.out.println(map);

给予

{
   a=[Item{code=1, name='dfg'}, Item{code=1, name='fdgdfdfgdg'}],
   b=[Item{code=1, name='dfg'}]
}

(*) 编辑:
正如 OP 所分享的,以下帖子有助于设计基于与流 API 的自定义等价关系的解决方案,当 distinct() 无法使用时:

  • Java 8 Distinct by property
  • Java 8 how to get distinct list on more than one property