如何编写自定义流功能

时间:2017-12-28 15:58:31

标签: java

我知道基本的流功能,如:

mystream.filter(something).map(something)

我有没有办法编写自己的函数,可以应用于像

这样的流
mystream.something()

链接必须能够继续像以下那样:

mystream.something().map()

2 个答案:

答案 0 :(得分:3)

您必须实现自己的库,它将已经存在的Stream界面包装在您自己的界面中:

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

然后,您必须获取Stream<T>的实例,然后将其包装到您自己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
}

通过上述内容,您可以创建CustomStream,如下所示:

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

唯一不好的是,从Stream继承的所有方法都会返回Stream<T>的实例而不是CustomStream<T>的实例。

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

因此,一旦您使用已经提供的API中的方法,您就会失去&#34;你的customStream。要克服这个问题,您必须覆盖界面中的方法:

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

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

然后在调用原始CustomStream<T> API中的方法时始终创建Stream<T>的新实例:

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

最后,您能够实现自己的目标:

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

我希望这可以提供有关如何解决问题的见解

答案 1 :(得分:1)

不,这是不可能的。

这需要扩展Stream接口。

修改

如Lino所述,您可以定义自己的子接口(或实现类)来添加这些新方法。

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

然后,您可能希望将Stream对象包装到MyStream对象中。