【问题标题】:Convert a List<Object> to a Map<String, List<Object>> and distinct the duplicates according to some properties of List's element?将 List<Object> 转换为 Map<String, List<Object>> 并根据 List 元素的某些属性区分重复项?
【发布时间】:2018-03-20 18:38:41
【问题描述】:

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

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

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

RawItem 列表如下:

[ { “类别”:“一个”, “代码”:1, “名称”:“项目 1” }, { “类别”:“一个”, “代码”:1, “名称”:“项目 1” }, { “类别”:“一个”, “代码”:2, “名称”:“项目 2” }, { “类别”:“b”, “代码”:1, “名称”:“项目 1” }, { “类别”:“b”, “代码”:1, “名称”:“项目 1” } ]

像这样把它变成Map&lt;String, List&lt;Item&gt;&gt;

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

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

【问题讨论】:

  • 请发布您的尝试
  • 如果主要是代码,那么你应该考虑更多地描述你的问题,告诉你在哪里找到问题(这需要发布你的尝试)
  • List&lt;RawItem&gt;Map&lt;String, Set&lt;Item&gt;&gt; 最好不过 Item 需要 equals+hashCode。
  • 我需要保留原始列表的顺序
  • 主要是代码,因为我引用了一些非代码作为代码,就是这样。问题已经描述清楚了

标签: java lambda collections java-stream functional-interface


【解决方案1】:

以下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 方法工作并删除重复项,您需要在RawItem 类中正确实现hashCodeequals 方法。

例如,下面的测试:

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 所分享的,当distinct() 无法使用时,以下帖子有助于设计基于与流 API 的自定义等效关系的解决方案:

【讨论】:

  • 这并不能完全解决问题,因为它不会删除具有相同内容(重复)的项目
  • @ClaudiuGuja 确实,修复了帖子。
  • 感谢您的及时回复,我会尝试一下 tmrw 因为在我提出这个问题后我已经下班了,我现在正在用我的手机发表评论......但是因为 distinct() 需要一个适当的equals 的实现,我怀疑它是否有效,因为我不能使用类别、代码、名称来唯一标识 RawItem,它还有其他未在此处列出的关键字段。那么还有其他解决方案作为补充吗?
  • @Wuaner:当然,我更新了帖子以考虑到这个额外的要求
  • @AlexandreDupriez 太棒了~现在无法测试它,因为周围没有电脑,但我知道它会工作!接受并再次感谢。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-11-23
  • 1970-01-01
  • 1970-01-01
  • 2018-09-22
  • 2015-11-21
相关资源
最近更新 更多