可以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/