提问者:小点点

如何编写自定义流函数


我知道基本的流函数,例如:

mystream.filter(something).map(something)

我有没有办法编写自己的函数,可以应用于如下流:

mystream.something()

链接必须能够像等一样继续:

mystream.something().map()

共2个答案

匿名用户

您必须实现自己的Library,它将已经存在的Stream接口与您自己的接口包装在一起:

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

这样,您就必须获取Stream的实例

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的实例

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

因此,一旦你使用了已经给出的API中的方法,你就会“丢失”你的自定义流。为了克服这个问题,你必须覆盖界面中的方法:

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

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

然后始终创建一个新的CustomStream实例

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); 

我希望这能让你了解如何解决你的问题

匿名用户

不,这是不可能的。

这将需要扩展Stream接口。

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

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

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