I want to fill an Array with generic Lists as Elements using a Supplier and Stream.generate.
Looks like this:
Supplier<List<Object>> supplier = () -> new ArrayList<Object>();
List<Object>[] test = (List<Object>[]) Stream.generate(supplier).limit(m).toArray();
With the Error output being:
Exception in thread "main" java.lang.ClassCastException: [Ljava.lang.Object; cannot be cast to [Ljava.util.List;
Now how do I fill an Array with a generic type using the techniques provided by Java 8? Or is that simply not possible (yet) and I have to do it the "classic" way?
Regards, Claas M
EDIT
Upon @Water's request I did a bit of performance testing with filling Arrays/Lists using stream.collect (With a Cast testing Arrays) and the traditional Method of iterating.
First the performance tests using Lists:
private static int m = 100000;
/**
* Tests which way is faster for LISTS.
* Results:
* 1k Elements: about the same time (~5ms)
* 10k Elements: about the same time (~8ms)
* 100k Elements: new way about 1.5x as fast (~18ms vs ~27ms)
* 1M Elements: new way about 2x as fast (~30ms vs ~60ms)
* NOW THIS IS INTERESTING:
* 10M Elements: new way about .1x as fast (~5000ms vs ~500ms)
* (100M OutOfMemory after ~40Sec)
* @param args
*/
public static void main(String[] args) {
Supplier<String> supplier = () -> new String();
long startTime,endTime;
//The "new" way
startTime = System.currentTimeMillis();
List<String> test1 = Stream.generate(supplier).limit(m ).collect(Collectors.toList());
endTime = System.currentTimeMillis();
System.out.println(endTime - startTime);
//The "old" way
startTime = System.currentTimeMillis();
List<String> test2 = new ArrayList();
Iterator<String> i = Stream.generate(supplier).limit(m).iterator();
while (i.hasNext()) {
test2.add(i.next());
}
endTime = System.currentTimeMillis();
System.out.println(endTime - startTime);
}
And second the Performance tests using Arrays:
private static int m = 100000000;
/**
* Tests which way is faster for ARRAYS.
* Results:
* 1k Elements: old way much faster (~1ms vs ~6ms)
* 10k Elements: old way much faster (~2ms vs ~7ms)
* 100k Elements: old way about 2x as fast (~7ms vs ~14ms)
* 1M Elements: old way a bit faster (~50ms vs ~60ms)
* 10M Elements: old way a bit faster (~5s vs ~6s)
* 100M Elements: Aborted after about 5 Minutes of 100% CPU Utilisation on an i7-2600k
* @param args
*/
public static void main(String[] args) {
Supplier<String> supplier = () -> new String();
long startTime,endTime;
//The "new" way
startTime = System.currentTimeMillis();
String[] test1 = (String[]) Stream.generate(supplier).limit(m ).collect(Collectors.toList()).toArray(new String[m]);
endTime = System.currentTimeMillis();
System.out.println(endTime - startTime);
//The "old" way
startTime = System.currentTimeMillis();
String[] test2 = new String[m];
Iterator<String> it = Stream.generate(supplier).iterator();
for(int i = 0; i < m; i++){
test2[i] = it.next();
}
endTime = System.currentTimeMillis();
System.out.println(endTime - startTime);
}
}
As you can see, Water was indeed right - the Cast makes it slower. But for Lists the new Method is faster; at least from 100k - 1M Elements. I still dont know why its so much slower when it comes to 10M Elements and I'd really like to hear some comment on that.