Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why is `Stream.collect` type-safe and `Stream.toArray(IntFunction<A[]>)` is not?

Consider the following code fragment

String strings[] = {"test"};
final List<String> collect = java.util.Arrays.stream(strings).collect(java.util.stream.Collectors.toList());
final Double[] array = java.util.Arrays.stream(strings).toArray(Double[]::new);

Why can Java guarantee the correct type in the collect-case (changing the generic type of collect to e.g. Double leads to a compile time error), but not in the array case (compiles fine, despite apply(int) of Double[]::new gives a Double[], not an Object[], but throws ArrayStoreException if used incorrectly as above)?

What would be the best way to generate a compile time error in case I change the type of the stream without changing the given IntFunction in the toArray call?

like image 961
muued Avatar asked May 21 '14 17:05

muued


People also ask

What is stream collect in Java?

Java Stream collect() is mostly used to collect the stream elements to a collection. It's a terminal operation. It takes care of synchronization when used with a parallel stream. The Collectors class provides a lot of Collector implementation to help us out.

Which method in stream can be used to create an array from the stream?

toArray() The toArray() method is a built-in method from the Stream class which is really convenient to use when converting from a Stream to an array.

What does stream () do in Java?

Introduced in Java 8, the Stream API is used to process collections of objects. A stream is a sequence of objects that supports various methods which can be pipelined to produce the desired result. A stream is not a data structure instead it takes input from the Collections, Arrays or I/O channels.


1 Answers

The signature of the method Stream::toArray looks as follows. Please note that the type parameters T and A are completely unrelated.

public interface Stream<T> {
    <A> A[] toArray(IntFunction<A[]> generator);
}

In the source of ReferencePipeline.java, you can find the following comment:

Since A has no relation to U (not possible to declare that A is an upper bound of U) there will be no static type checking. Therefore use a raw type and assume A == U rather than propagating the separation of A and U throughout the code-base. The runtime type of U is never checked for equality with the component type of the runtime type of A[]. Runtime checking will be performed when an element is stored in A[], thus if A is not a super type of U an ArrayStoreException will be thrown.

like image 122
nosid Avatar answered Sep 17 '22 20:09

nosid