Currently, the toList()
collector is implemented using and returning an ArrayList
(note that the container used during collection does not always have to match the type of final results). The path, the collector interface is defined, the collector has no chance of pre-selecting the list.
But in principle, since the standard Stream implementation and the predefined collector implementation of toList()
are part of the same library, there may be a non-standard connection in future implementations (or alternative JREs), where the stream detects the toList()
in the collect
method and performs an optimized operation . But when the toList()
collector is used, for example, as the downstream collector of the groupingBy
collector, in any case there is no predicted size.
If you assume that a stream can predict its size, for example, in your example myList.stream().map(doWhatever)
, the most efficient solution, given the current implementation, is
List<ElementType> result=Arrays.asList(stream.toArray(ElementType[]::new));
since this operation will use a known size, even in parallel, or, especially when used with parallel flow, when splitting sub-sizes are predictable, since then no merging step is required, that is, all employees will write directly to the results array.
Unfortunately, if ElementType
not a reproducible type, you must resort to an unverified operation here.
If sizes are not predictable, this solution may be even more efficient compared to the current toList()
collector, but may be lost compared to a future implementation that may use non-linear storage.
Thus, the optimized option is only suitable for a specific setting. For most scenarios, the toList()
collector is sufficient or maybe even better than any alternative in possible future implementations.