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.
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.
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.
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.
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.
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();
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With