为什么Collectors.toList()不能处理原始集合? [英] Why doesn't Collectors.toList() work on primitive collections?
问题描述
(这可能与 https://stackoverflow.com/a/30312177/160137 有关,但我'我担心我仍然没有得到它。所以我这样问我的问题,希望它会导致我更容易理解的答案。)
(This is probably related to https://stackoverflow.com/a/30312177/160137, but I'm afraid I still don't get it. So I'm asking my question this way, in the hope that it'll lead to an answer I can more easily understand.)
通常当我有一个Stream时,我可以使用Collectors类中的一个静态方法将它转换为一个集合:
Normally when I have a Stream I can convert it to a collection using one of the static methods in the Collectors class:
List<String> strings = Stream.of("this", "is", "a", "list", "of", "strings")
.collect(Collectors.toList());
类似的过程不适用于原始流,但正如其他人注意到的那样:
The similar process doesn't work on primitive streams, however, as others have noticed:
IntStream.of(3, 1, 4, 1, 5, 9)
.collect(Collectors.toList()); // doesn't compile
我可以这样做:
IntStream.of(3, 1, 4, 1, 5, 9)
.boxed()
.collect(Collectors.toList());
或者我可以这样做:
IntStream.of(3, 1, 4, 1, 5, 9)
.collect(ArrayList<Integer>::new, ArrayList::add, ArrayList::addAll);
问题是,为什么Collectors.toList()只对原始流执行此操作?难道没有办法指定包装类型吗?如果是这样,为什么这不起作用:
The question is, why doesn't Collectors.toList() just do that for primitive streams? Is it that there's no way to specify the wrapped type? If so, why doesn't this work either:
IntStream.of(3, 1, 4, 1, 5, 9)
.collect(Collectors.toCollection(ArrayList<Integer>::new)); // nope
任何见解都将受到赞赏。
Any insight would be appreciated.
推荐答案
好吧,让 IntStream
提供带签名的方法是没有问题的?
< R,A> R collect(Collector<?super Integer,A,R> collector)
执行隐式装箱。它可以简单地实现为返回boxed()。collect(collector);
。
Well, it would be no problem to let IntStream
provide a method with the signature
<R,A> R collect(Collector<? super Integer,A,R> collector)
performing an implicit boxing. It could be implemented as simple as return boxed().collect(collector);
.
问题是它为什么要或者反过来:为什么原始流特化存在呢?
The question is "why should it" or the other way round: why do the primitive stream specializations exist at all?
它们仅仅出于性能原因而存在,提供没有装箱开销的流操作。因此,显而易见的设计决定是不包括通用 Stream
接口中已存在的任何操作,因为所有这些操作都可以简单地调用 boxed()。 genericOperation(...)
。
They merely exist for performance reasons, to offer stream operations without boxing overhead. So it’s an obvious design decision not to include any operation which already exists in the generic Stream
interface as for all these you can simply invoke boxed().genericOperation(…)
.
答案,您已链接地址相关但不同的想法。它是关于提供一个 collect
方法,不接受泛型收集器
,但是一个原始的特化,如收集器.ofInt
可以在没有装箱的情况下收集 int
值,但是对于产生 List< Integer> $的收集器c $ c>,不可避免地包含盒装值,它没有任何好处。
在预建的收藏家中,只有少数人真的可以避免拳击。所有这些都作为原始流的显式终端操作提供( count()
, sum()
, min()
, max()
, summaryStatistics()
,... )
The answer, you have linked addresses a related, but different idea. It’s about providing a collect
method not accepting the generic Collector
, but a primitive specialization like Collector.ofInt
which could collect int
values without boxing, but for a collector which produces a List<Integer>
, unavoidably containing boxed values, it wouldn’t have any benefit.
Amongst the prebuilt collectors, only a few really could avoid boxing. All of them are provided as explicit terminal operations on the primitive streams (count()
, sum()
, min()
, max()
, summaryStatistics()
, …)
这是类/接口数量和潜在性能增益之间的权衡。对于一般的流,决定创建 IntStream
, LongStream
和 DoubleStream
,但在收藏家的情况下,决定不添加此类专业化。
It’s a trade-off between number of classes/interfaces and potential performance gain. In the case of streams in general, the decision was to create IntStream
, LongStream
and DoubleStream
, but in case of the collectors, the decision was not to add such specializations.
这篇关于为什么Collectors.toList()不能处理原始集合?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!