Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why do the new Java 8 streams return an Object Array on toArray calls?

Tags:

java

java-8

Whilst I was working on a project involving Java 8's new streams, I noticed that when I called Stream#toArray() on a stream, it return an Object[] instead of a T[]. Surprised as I was, I started digging into the source code of Java 8 and couldn't find any reason why they didn't implement Object[] toArray(); as T[] toArray();. Is there any reasoning behind this, or is it just an (in)consistency?

EDIT 1: I noticed in the answers that a lot of people said this would not be possible, but this code snippet compiles and return the expected result?

import java.util.Arrays;

public class Test<R> {

    private Object[] items;

    public Test(R[] items) {
        this.items = items;
    }

    public R[] toArray() {
        return (R[]) items;
    }

    public static void main(String[] args) {
        Test<Integer> integerTest = new Test<>(new Integer[]{
            1, 2, 3, 4
        });

        System.out.println(Arrays.toString(integerTest.toArray()));
    }

}
like image 712
Martijn Avatar asked Oct 30 '14 21:10

Martijn


People also ask

Which of the following is correct about streams in Java 8?

i) Stream represents a sequence of objects from a source, which supports aggregate operations.

Why are streams introduced in Java 8?

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.


2 Answers

Try:

String[] = IntStream.range(0, 10).mapToObj(Object::toString).toArray(String[]::new);

The no-arg toArray() method will just return an Object[], but if you pass an array factory (which can be conveniently represented as an array constructor reference), you can get whatever (compatible) type you like.

like image 76
Brian Goetz Avatar answered Oct 20 '22 00:10

Brian Goetz


This is the same problem that List#toArray() has. Type erasure prevents us from knowing the type of array we should return. Consider the following

class Custom<T> {
    private T t;
    public Custom (T t) {this.t = t;}
    public T[] toArray() {return (T[]) new Object[] {t};} // if not Object[], what type?
}

Custom<String> custom = new Custom("hey");
String[] arr = custom.toArray(); // fails

An Object[] is not a String[] and therefore cannot be assigned to one, regardless of the cast. The same idea applies to Stream and List. Use the overloaded toArray(..) method.

like image 45
Sotirios Delimanolis Avatar answered Oct 20 '22 01:10

Sotirios Delimanolis