6

I know of the basic stream functions like:

mystream.filter(something).map(something)

Is there a way for me to write my own function that can be applied to a stream like:

mystream.something()

Chaining would have to be able to continue like etc.:

mystream.something().map()
Gratus D.
  • 787
  • 7
  • 22

2 Answers2

13

You'd have to implement your own Library which is wrapping the already existant Stream interface with your own:

interface CustomStream<T> extends Stream<T> {
    CustomStream<T> something();
}

That way you then have to aquire an instance of Stream<T> and then wrap it into an implementation of your own interface:

class CustomStreamImpl<T> implements CustomStream<T>{
    private final Stream<T> stream;

    public CustomStreamImpl(Stream<T> stream){
        this.stream = stream;
    }

    public CustomStreamImpl<T> something(){
        // your action below
        Stream<T> newStream = stream
            .filter(o -> o != null)
            .collect(Collectors.toList())
            .stream(); 
        return new CustomStreamImpl<T>(newStream);
    }

    // delegate all the other methods to private stream instance
}

With the above you then could create a CustomStream like the following:

CustomStream<String> stream = new CustomStreamImpl<>(Stream.of("Hello", "World"));

The only bad thing is that all the methods inherited from Stream will return an instance of Stream<T> and not one of CustomStream<T>.

CustomStream<String> stream = new CustomStreamImpl<>(Stream.of("Hello", "World"));
// returns not CustomStream
Stream<String> newStream = stream.filter(s -> s.equals("Hello")); 

So once you use a method from the already given API you'll "lose" your customStream. To overcome this you'd have to override the methods in your interface:

interface CustomStream<T> extends Stream<T> {
    CustomStream<T> something();

    CustomStream<T> filter(Predicate<? super T> tester);
    // all the other methods
}

and then create always a new Instance of CustomStream<T> when a method from the original Stream<T> API is called:

public CustomStreamImpl<T> filter(Predicate<? super T> tester){
    return new CustomStreamImpl<T>(stream.filter(tester));
}

Finally you're able to achieve you're chanining:

CustomStream<String> stream = new CustomStreamImpl<>(Stream.of("Hello", "World"));
stream
    .filter(s -> s.equals("Hello"))
    .something()
    .map(String::length)
    .something()
    .forEach(System.out::println); 

I hope this gives insight on how to approach your problem

Lino
  • 19,604
  • 6
  • 47
  • 65
-3

No this is not possible.

This would require extending the Stream interface.

Edit

As mentioned by Lino, you could define your own sub-interface (or implementing class) that adds those new methods.

interface MyStream<T> extends Stream<T> {
    public MyStream<T> something();
}

You would then probably want to wrap a Stream object into a MyStream object.

Ward
  • 2,799
  • 20
  • 26