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

mystream.filter(something).map(something)


有没有一种方法可以编写我自己的函数,该函数可以应用于像这样的流:

mystream.something()


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

mystream.something().map()

最佳答案

您必须实现自己的库,用自己的库包装已经存在的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中的方法,就会“丢失”您的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);


我希望这能为您提供解决方法方面的见识

08-28 22:02