java - 如何分组到数组映射中?

标签 java arrays java-stream grouping

可以groupingBy对流的操作会生成一个映射,其中的值是数组,而不是列表或其他一些集合类型?

例如:我有一个类 Thing .物有主,所以Thing有一个 getOwnerId方法。在事物流中,我想按所有者 ID 对事物进行分组,以便具有相同所有者 ID 的事物最终一起出现在一个数组中。换句话说,我想要一个如下所示的映射,其中键是所有者 ID,值是属于该所有者的数组。

    Map<String, Thing[]> mapOfArrays;

在我的例子中,由于我需要将 map 值传递给需要数组的库方法,因此将其收集到 Map<String, Thing[]> 中最为方便。 .

将整个流收集到一个数组中很容易(甚至不需要显式收集器):

    Thing[] arrayOfThings = Stream.of(new Thing("owner1"), new Thing("owner2"), new Thing("owner1"))
            .toArray(Thing[]::new);

[Belongs to owner1, Belongs to owner2, Belongs to owner1]

通过所有者 ID 搜索也很容易。例如,分组到列表中:

    Map<String, List<Thing>> mapOfLists = Stream.of(new Thing("owner1"), new Thing("owner2"), new Thing("owner1"))
            .collect(Collectors.groupingBy(Thing::getOwnerId));

{owner1=[Belongs to owner1, Belongs to owner1], owner2=[Belongs to owner2]}

只有这个例子给了我一个列表的 map 。有 2-arg 和 3-arg groupingBy可以给我其他集合类型(如集合)的 map 的方法。我想,如果我可以将收集到数组中的收集器(类似于上面第一个片段中的收集到数组中)传递给双参数 Collectors.groupingBy​(Function<? super T,? extends K>, Collector<? super T,A,D>) ,我会被设置。但是,Collectors 中没有预定义的收集器类似乎对数组做任何事情。我错过了一个不太复杂的方法吗?

为了一个完整的示例,这里是我在上面的代码片段中使用的类:

public class Thing {

    private String ownerId;

    public Thing(String ownerId) {
        this.ownerId = ownerId;
    }

    public String getOwnerId() {
        return ownerId;
    }

    @Override
    public String toString() {
        return "Belongs to " + ownerId;
    }

}

最佳答案

使用来自 this answer by Thomas Pliakas 的收集器:

    Map<String, Thing[]> mapOfArrays = Stream.of(new Thing("owner1"), new Thing("owner2"), new Thing("owner1"))
            .collect(Collectors.groupingBy(Thing::getOwnerId,
                    Collectors.collectingAndThen(Collectors.toList(),
                            tl -> tl.toArray(new Thing[0]))));

想法是首先收集到一个列表中(这是一个显而易见的想法,因为数组具有恒定大小),然后在返回到分组依据 收集器之前转换为数组。 collectingAndThen 可以通过其所谓的 finisher 来做到这一点。

打印检查结果:

    mapOfArrays.forEach((k, v) -> System.out.println(k + '=' + Arrays.toString(v)));
owner1=[Belongs to owner1, Belongs to owner1]
owner2=[Belongs to owner2]

编辑:感谢 Aomine 提供的链接:使用 new Thing[0] 作为 toArray 的参数的灵感来自 Arrays of Wisdom of the Ancients .似乎在 Intel CPU 上最终使用 new Thing[0] 比使用 new Thing[tl.size()] 更快。我很惊讶。

关于java - 如何分组到数组映射中?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53695027/

相关文章:

java - 动态绑定(bind)Java

java - 我需要帮助在 android 查询生成器中选择不同的列值

c - Getcontext() 适用于具有结构的数组元素

java - 检测流中的重复组

java - 一步进行分组和过滤

通过套接字发送图像时的Java OutOfMemory

java - 使用 Maven 的并行库版本

谁能解释为什么下面的程序什么都不输出?

c# - 如何在 C# 中快速将二维数组转换为一维数组?

Java 8 流 : find items from one list that match conditions calculated based on values from another list