我正在尝试将Map列表合并为一个:
List<Map<String, List<Long>>> dataSet;
Map<String, Set<Long>> uniqueSets = dataset.stream()
.flatMap(m -> m.entrySet().stream())
.collect(Collectors.groupingBy(
Map.Entry::getKey,
Collector.of(
HashSet<Long>::new,
...,
...
)
));
这个想法是uniqueSet
应该在每个集合中保存一个唯一ID(Longs)列表(由String标识)。但我不确定...
部分。
至于请求的示例(在JSON中):
输入:
[
{
"Collection1": [1, 2, 3, 3],
"Collection2": [2, 3]
},
{
"Collection1": [3, 4],
"Collection3": [1, 2]
}
]
输出:
{
"Collection1": [1, 2, 3, 4],
"Collection2": [2, 3],
"Collection3": [1, 2]
}
答案 0 :(得分:2)
如果我理解了你的问题,如果给出这两张地图:
<!DOCTYPE html>
<!--
To change this license header, choose License Headers in Project Properties.
To change this template file, choose Tools | Templates
and open the template in the editor.
-->
<html>
<head>
<title>Shopping</title>
<script type="text/javascript" src="JavaScript.js"></script>
</head>
<body>
<div id="results"></div>
<button type="button" id="addButton">Add one item</button>
<button type="button" id="removeButton">Remove one item</button>
</body>
</html>
你想要像这样组合它们:
{Mike=[5, 6], Jack=[1, 2, 3]}
{Fred=[7, 8], Jack=[4, 5]}
你走了:
{Mike=[5, 6], Fred=[7, 8], Jack=[1, 2, 3, 4, 5]}
那是:
Map<String, List<Long>> uniqueSets = dataset.stream()
.flatMap(m -> m.entrySet().stream())
.collect(Collectors.groupingBy(
Map.Entry::getKey,
Collector.of(
ArrayList<Long>::new,
(list, item) -> list.addAll(item.getValue()),
(left, right) -> { left.addAll(right); return left; })
));
以累积值ArrayList
个实例。答案 1 :(得分:1)
你可以使用这样的东西
Map<String, List<Long>> uniqueSets = dataset.stream()
.flatMap(m -> m.entrySet().stream())
.collect(Collectors.groupingBy(
Map.Entry::getKey,
Collector.of(
ArrayList<Long>::new,
(x, y) -> { x.addAll(y.getValue()); },
(x, y) -> {
List<Long> r = new ArrayList<>(x);
r.addAll(y);
return r;
}
)
));
修改强>
其他方法是
Map<String, List<Long>> uniqueSets = dataset.stream()
.flatMap(m -> m.entrySet().stream())
.flatMap(e -> e.getValue().stream().map(v -> new Pair(e.getKey(), v)))
.collect(Collectors.groupingBy(
Pair::getKey,
Collectors.mapping(
Pair::getValue,
Collectors.toList()
))
);
但它需要配对类(你可以在许多库中找到类似的类)
class Pair {
final String key;
final Long value;
public Pair(String key, Long value) {
this.key = key;
this.value = value;
}
public String getKey() {
return key;
}
public Long getValue() {
return value;
}
}
答案 2 :(得分:0)
这样的事情怎么样:
Map<String, Set<Long>> uniqueSets = new HashMap<>();
dataset.forEach(map -> map.forEach((string, list) -> {
if (uniqueSets.get(string) != null){
list.forEach(id -> uniqueSets.get(string).add(id));
}else{
uniqueSets.put(string, new HashSet<>(list));
}
}));
答案 3 :(得分:0)
试试这个。
Map<String, List<Long>> r =
dataSet.stream()
.flatMap(e -> e.entrySet().stream())
.flatMap(e -> e.getValue().stream()
.map(v -> new AbstractMap.SimpleEntry<String, Long>(e.getKey(), v)))
.distinct()
.collect(Collectors.groupingBy(
Entry::getKey,
Collectors.mapping(Entry::getValue, Collectors.toList())));
System.out.println(dataSet);
System.out.println(r);
结果:
[{Collection1=[1, 2, 3, 3], Collection2=[2, 3]}, {Collection1=[3, 4], Collection3=[1, 2]}]
{Collection1=[1, 2, 3, 4], Collection3=[1, 2], Collection2=[2, 3]}
答案 4 :(得分:0)
正如您特别要求使用自定义收集器的基于流的解决方案,这是一种方式:
List<Map<String, List<Long>>> dataSet;
Map<String, Set<Long>> uniqueSets = dataset.stream()
.flatMap(m -> m.entrySet().stream())
.collect(Collectors.groupingBy(
Map.Entry::getKey,
Collector.of(
HashSet<Long>::new,
(set, e) -> set.addAll(e.getValue()),
(left, right) -> { left.addAll(right); return left; })));
但是,我认为没有流可以提供更好的解决方案:
Map<String, Set<Long>> uniqueSets = new HashMap<>();
dataSet.forEach(map ->
map.forEach((k, v) -> uniqueSets.merge(
k,
new HashSet<>(v),
(o, n) -> { o.addAll(n); return o; })));
迭代遍历映射列表,并且对于每个映射,它迭代其条目,以便对于每个映射的每个键/值对,将值转换为映射到其的HashSet
。 uniqueSets
地图中的关键字。这是通过Map.merge
方法实现的,如果条目中不存在该条目,则创建条目,或者如果已存在该值的键,则将新值与旧值合并。对于此合并,我使用的是Set.addAll
。