[英]Convert Java list into map where each value in map shares same attribute, using streams
我正在尝试将列表转换为映射,以便对于列表元素的某些属性,映射的键是元素 ID,值是具有相同属性的元素的其他元素 ID。 这使用for
循环相当简单,但我试图仅使用 Java 流来做到这一点。 主要目标是可读性,而不是性能。
下面是它在 for 循环中的样子 - 在这个例子中属性是colorId
:
class Apple {
int _appleId; // different for each apple
int _colorId; // same for some apples
Apple(int appleId, int colorId) {
_appleId = appleId;
_colorId = colorId;
}
int getAppleId() { return _appleId; }
int getColorId() { return _colorId; }
}
public static void main(String[] args) {
Apple apple1 = new Apple(1, 7);
Apple apple2 = new Apple(2, 7);
Apple apple3 = new Apple(3, 7);
Apple apple4 = new Apple(4, 8);
Apple apple5 = new Apple(5, 8);
Apple apple6 = new Apple(6, 9);
List<Apple> apples = List.of(apple1, apple2, apple3, apple4,
apple5, apple6);
// applesByColor: {7=[1, 2, 3], 8=[4, 5], 9=[6]}
Map<Integer, Set<Integer>> applesByColor = apples.stream().collect(
Collectors.groupingBy(Apple::getColorId,
Collectors.mapping(Apple::getAppleId, Collectors.toSet())));
// applesWithSameColor:
// {1=[1, 2, 3], 2=[1, 2, 3], 3=[1, 2, 3], 4=[4, 5], 5=[4, 5], 6=[6]}
Map<Integer, Set<Integer>> applesWithSameColor = new HashMap<>();
for (var entry : applesByColor.entrySet()) {
for (var appleId : entry.getValue()) {
applesWithSameColor
.computeIfAbsent(appleId, k -> new HashSet<>())
.addAll(entry.getValue());
}
}
}
这是我对applesWithSameColor
理想结果:
best: {1=[2, 3], 2=[1, 3], 3=[1, 2], 4=[5], 5=[4]}
better: {1=[2, 3], 2=[1, 3], 3=[1, 2], 4=[5], 5=[4], 6=[]}
good: {1=[1, 2, 3], 2=[1, 2, 3], 3=[1, 2, 3], 4=[4, 5], 5=[4, 5], 6=[6]}
该示例显示了good
输出。
使用 Java 流执行此操作的好方法是什么? 如果我们也可以避免创建中间地图applesByColor
,那将是理想的。
您可以从applesByColor
Map 流式传输值,然后为Set
每个值创建条目,然后将它们收集到Map
Map<Integer, Set<Integer>> applesWithSameColor = applesByColor.values().stream()
.flatMap(set -> set.stream().map(val -> Map.entry(val, set)))
.collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue));
在重复键的情况下,您还可以使用合并功能,以避免冲突
collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue, (v1, v2) ->v1)));
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.