Why doesn't Collectors.toList() work on primitive collections?

强颜欢笑 提交于 2019-12-05 05:35:54
Holger

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?

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(…).

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(), …)

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.

For primitive types List<> is an added suboptimal usage. Hence toArray was deemed sufficient and adequate (=optimal usage).

int[] array = IntStream.of(3, 1, 4, 1, 5, 9).toArray();
IntStream.of(3, 1, 4, 1, 5, 9)
    .collect(Collectors.toList());  // doesn't compile

The stream is int, the generic method toList() assumes an object. No match.

IntStream.of(3, 1, 4, 1, 5, 9)
    .boxed()
    .collect(Collectors.toList());

The stream is Integer, the generic method toList() assumes an object. Match!

IntStream.of(3, 1, 4, 1, 5, 9)
    .collect(ArrayList<Integer>::new, ArrayList::add, ArrayList::addAll);

The stream is int, and it's like fixing the generic method toList() to Integer. Except that IntStream doesn't have a collect() method that accepts a collector, only a 3-parameter method.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!