将 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] 中的 hashCode
和 equals
方法=] 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
例如,对于两个 类 这样的:
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] 中的 hashCode
和 equals
方法=] 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