Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Java8 streams and typecasts

Can anybody explain to me why the following code is not working?

I was trying to get a feel for the new features of Java8 and solved the BerlinClock Kata. During this I had to parse a String in the format "hh:mm:ss" - I wanted to use streams and wrote the following piece of code.

import java.util.Arrays;

private Integer[] parseTime (String time){
    Integer[] hhmmss = (Integer[]) Arrays.stream(time.split(":"))
                                         .map(s->Integer.parseInt(s)).toArray();
    return hhmmss;
}

but the runtime system (I think) is complaining that the explicit type cast (Integer[]) cannot be done.

As far as I understand it the Arrays.stream(time.split(":")) part returns a Stream<String>, then map(s->Integer.parseInt(s)) converts this to Stream<Integer>, then toArray() produces an Object[]. Now a type cast to Integer[] should be possible as the intermediate stream was had an Integer type-parameter.

Note that I know how to solve this problem without type cast by using

int[] hhmmss= Arrays.stream(time.split(":")
                    .mapToInt(Integer::parseInt).toArray();

and changing the type signature accordingly to int[] parseTime. But I do not understand why there is a problem in the type-cast.

like image 620
epsilonhalbe Avatar asked Mar 15 '14 16:03

epsilonhalbe


People also ask

Does Java 8 support streams?

Java 8 offers the possibility to create streams out of three primitive types: int, long and double. As Stream<T> is a generic interface, and there is no way to use primitives as a type parameter with generics, three new special interfaces were created: IntStream, LongStream, DoubleStream.

What is the difference between collections and stream in Java8?

Differences between a Stream and a Collection: A stream does not store data. An operation on a stream does not modify its source, but simply produces a result. Collections have a finite size, but streams do not.

Is Java 8 stream faster than for loop?

The short version basically is, if you have a small list; for loops perform better, if you have a huge list; a parallel stream will perform better. And since parallel streams have quite a bit of overhead, it is not advised to use these unless you are sure it is worth the overhead.

Does Java 8 stream improve performance?

In Java8 Streams, performance is achieved by parallelism, laziness, and using short-circuit operations, but there is a downside as well, and we need to be very cautious while choosing Streams, as it may degrade the performance of your application.


1 Answers

For the first case, Stream#map() method will give you a Stream<Integer>, and then Stream#toArray() returns an Object[], which you need to cast to Integer[]. But at runtime, this cast may fail, if internally an Object[] is created instead of an Integer[], which is the case here. The source code of toArray() method for this stream looks like this:

@Override
public final Object[] toArray() {
    return toArray(Object[]::new);
}

And you can't cast an Object[] to an Integer[] reference.

You can solve this issue by using Stream#toArray(IntFunction) instead, and then you wouldn't need a cast:

private Integer[] parseTime (String time){
    Integer[] hhmmss = Arrays.stream(time.split(":"))
                    .map(s->Integer.valueOf(s))
                    .toArray(Integer[]::new);
    return hhmmss;
}

In second case however, Stream#mapToInt() method gives you an IntStream, and IntStream#toArray() returns an int[], and hence no casting required there.

like image 122
Rohit Jain Avatar answered Sep 29 '22 15:09

Rohit Jain