我知道基本的流功能,如:
mystream.filter(something).map(something)
我有没有办法编写自己的函数,可以应用于像
这样的流mystream.something()
链接必须能够继续像以下那样:
mystream.something().map()
答案 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对象中。