如何从对流创建集合映射?

时间:2021-05-18 14:10:32

标签: java java-stream

我在创建包含集合的映射时遇到特定 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() { /*...*/ }
}

1 个答案:

答案 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