我有一个List<Set<Integer>>
,想要一个Map<Integer, List<Set<Integer>>>
,它会将每个Integer
映射到包含sets
的所有Integer
。
这里显而易见的候选人将使用Collectors.groupingBy
,但它不起作用,因为groupingBy
只允许返回一个键的分类器函数。我需要为每个Set
返回几个键。
List<Set<Integer>> setList ...;
Map<Integer, List<Set<Integer>>> setMap = setList.stream().collect(
groupingBy(eachSet -> ))
以下是我想要在不使用流的情况下实现的一个示例:
List<Set<Integer>> setList ...
System.out.print("setList: ");
System.out.println(setList);
Map<Integer, List<Set<Integer>>> setMap = new HashMap<>();
for(Set<Integer> eachSet: setList) {
for(Integer i: eachSet) {
List<Set<Integer>> newSetList = setMap.getOrDefault(i, new ArrayList<>());
newSetList.add(eachSet);
setMap.putIfAbsent(i, newSetList);
}
}
System.out.print("setMap: ");
System.out.println(setMap);
这将输出以下内容:
setList: [[1], [1], [1, 3], [2, 3, 7]]
setMap: {1=[[1], [1], [1, 3]], 2=[[2, 3, 7]], 3=[[1, 3], [2, 3, 7]], 7=[[2, 3, 7]]}
答案 0 :(得分:3)
两种方法:
在所有集合中生成所有整数的流,然后将整数与包含它的所有集合相关联。
Map<Integer, List<Set<Integer>>> m1 =
list.stream().flatMap(Set::stream)
.distinct()
.collect(
Collectors.toMap(a -> a,
b -> list.stream().filter(set -> set.contains(b)).collect(Collectors.toList()))
);
创建一个中间地图,将集合的元素映射到自身,然后将这些条目合并到最终地图中。
Map<Integer, List<Set<Integer>>> m2 = list.stream()
.map(x -> x.stream().collect(Collectors.toMap(a -> a, b -> x)))
.flatMap(x -> x.entrySet().stream())
.collect(
Collectors.toMap(Map.Entry::getKey,
a -> List.of(a.getValue()), (l1, l2) -> Stream.concat(l1.stream(), l2.stream()).collect(Collectors.toList()))
);
答案 1 :(得分:1)
请注意,您的for
循环变体不必要地复杂化。您可以使用单个getOrDefault
:
putIfAbsent
加computeIfAbsent
for(Set<Integer> eachSet: setList) {
for(Integer i: eachSet) {
List<Set<Integer>> setList = setMap.computeIfAbsent(i, key -> new ArrayList<>());
setList.add(eachSet);
}
}
允许简化链式操作:
for(Set<Integer> eachSet: setList) {
for(Integer i: eachSet) {
setMap.computeIfAbsent(i, key -> new ArrayList<>()).add(eachSet);
}
}
等效的Stream操作将是:
Map<Integer, List<Set<Integer>>> setMap = setList.stream()
.flatMap(set -> set.stream().map(i -> new AbstractMap.SimpleImmutableEntry<>(i, set)))
.collect(groupingBy(Map.Entry::getKey, mapping(Map.Entry::getValue, toList())));
答案 2 :(得分:0)
使用forEach
:
List<Set<Integer>> setList = ...;
Map<Integer, List<Set<Integer>>> setMap = new HashMap<>();
setList.stream().forEach(val -> { //set<Integer>
val.stream().forEach(i -> { //Integer
List<Set<Integer>> newSetList = setMap.getOrDefault(i, new ArrayList<>());
newSetList.add(val);
setMap.putIfAbsent(i, newSetList);
});
});