Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Java 8 extending stream<T>

I'm attempting to extend Java 8's Stream implementation.

I have this interface:

public interface StreamStuff<T> extends Stream<T> {

    Stream<T> delegate();
    default Stream<T> biggerThanFour() {
        return delegate().filter(i -> ((Double)i > 4));
    }
}

And in my main method:

int arr [] = {1,2,3,4,5,6};

Object array [] = ((StreamStuff)Arrays
            .stream(arr))
            .biggerThanFour()
            .toArray();

I'm trying to cast the Stream, to my interface StreamStuff, and use my method.

Im getting the following error:

Exception in thread "main" java.lang.ClassCastException: java.util.stream.IntPipeline$Head cannot be cast to StreamStuff

I get the same error when I do:

StreamStuff ss = (StreamStuff)Arrays.stream(arr);

I'm wondering if this sort of thing is even possible and if so, how do I achieve this? For reference I'm kind of using this article as a guide.

like image 481
Liam Ferris Avatar asked Oct 11 '16 14:10

Liam Ferris


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.

Is Java 8 stream faster than for loop?

Yes, streams are sometimes slower than loops, but they can also be equally fast; it depends on the circumstances. The point to take home is that sequential streams are no faster than loops.

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.

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.


2 Answers

You are calling stream() on the Arrays class, which creates its own Stream implementation without any connection to yours. You'd have to produce the Stream yourself, or wrap a stream you obtained elsewhere, in order for something like this to work. Something like this:

int[] filtered = new StreamStuff(Arrays.stream(arr)).biggerThanFour().toArray();

However, in your case, why don't you just filter?

int[] filtered = Arrays.stream(arr).filter(i -> i > 4).toArray();
like image 194
erickson Avatar answered Sep 20 '22 15:09

erickson


As already mentioned, you can create your own wrapper implementation:

public class MyStream<T> implements Stream<T> {

    private final Stream<T> delegate;

    public MyStream(Stream<T> delegate) {
        this.delegate = delegate;
    }

    @Override
    public Stream<T> filter(Predicate<? super T> predicate) {
        return delegate.filter(predicate);
    }

    @Override
    public void forEach(Consumer<? super T> action) {
        delegate.forEach(action);
    }

    MyStream<T> biggerThanFour() {
        return new MyStream<>(delegate.filter(i -> ((Double) i > 4)));
    }

    // all other methods from the interface
}

You will have to delegate all methods from the interface, so the class will be pretty big. You might consider adding a class StreamWrapper which will delegate all methods from the interface and then have your actual class StreamStuff extend StreamWrapper. This would allow you to have only your custom methods in StreamStuff and no other stream methods. You might also make all overridden methods in StreamWrapper final to avoid accidentally overriding them.

Then you can use it like this:

public static void main(String[] args) {
    Stream<Double> orgStream = Stream.of(1.0, 3.0, 7.0, 2.0, 9.0);

    MyStream<Double> myStream = new MyStream<>(orgStream);

    myStream.biggerThanFour().forEach(System.out::println);
}

The custom method returns a new wrapper so you can chain calls to your custom methods.

Just note that your cast to Double might throw ClassCastException so you might consider replacing generic T with Double, hence limiting the delegate stream to be of that specific type.

like image 28
Jaroslaw Pawlak Avatar answered Sep 17 '22 15:09

Jaroslaw Pawlak