我在创建包含集合的映射时遇到特定 Java 流的问题。 我找到了一种方式,但我觉得有一种更好(更高效或更具可读性)的方式来表达这一点。
如果您有任何改进此功能的想法,我们将不胜感激!
输入:
[["A", 1], ["A", 2], ["B", 3], ["D", 1], ["D", 5]]
输出:
["A"={1, 2}, "B"={3}, "D"={1, 5}]
public static <L, R> Map<L, Set<R>> pairsToMap(Stream<Pair<L, R>> pairs) {
return pairs.collect(
Collectors.toMap(Pair::getLeft,
// FIXME: Creating a new HashSet for each Pair... :/
p -> new HashSet<>(Collections.singleton(p.getRight())),
// merge existing set with new set
(a, b) -> {
a.addAll(b);
return a;
}
)
);
}
注意: Pair 是我自己的实现,基本上如下:
public class Pair<L, R> {
/* ... */
public L getLeft() { /*...*/ }
public R getRight() { /*...*/ }
}
答案 0 :(得分:2)
这更像是 groupingBy
而不是 toMap
:
public static <L, R> Map<L, Set<R>> pairsToMap(Stream<Pair<L, R>> pairs) {
return pairs.collect(Collectors.groupingBy(
Pair::getLeft,
Collectors.mapping(Pair::getRight, Collectors.toSet())
));
}
groupingBy
允许您指定进一步收集每个组的方法。在这种情况下,我们要先映射到正确的元素,然后是 toSet
。