重用流操作链

Wol*_*llo 2 java java-stream

我正在寻找一种可读的方式来重用流操作链。

我的想法是,我有一定的操作序列,我想将其应用于其他操作之间的多个流。流之间的其他操作并不相同。

因此,例如,对于每个流,我想更改字符串的大小写,修剪它,使空字符串无效,然后过滤掉空值,最后消除重复项,如下所示:

在这两种情况下,我都会执行以下操作序列:

.map( String::trim ).map( Strings::emptyToNull ).filter( Objects::nonNull ).distinct()
Run Code Online (Sandbox Code Playgroud)

我目前复制该链并将其放在多个流的其他操作之间:

myStream1.doSomeStuff().map( String::trim ).map( Strings::emptyToNull ).filter( Objects::nonNull ).distinct().doOtherStuff();

myStream2.doSomethingElse().map( String::trim ).map( Strings::emptyToNull ).filter( Objects::nonNull ).distinct().doSomethingElseStill();
Run Code Online (Sandbox Code Playgroud)

有没有好的方法可以避免重写那段代码?显然,两个 map() 操作是可能的,但是有没有办法实现这种操作组合呢?

Yas*_*jaj 5

你可以将你的包裹Stream<String>在一个函数中

public Stream<String> trimAndFilterOutEmptyStringsAndGetDistinctElements(Stream<String> stream) {
    return stream.map(String::trim)
                 .map(Strings::emptyToNull) // or use not(String::isEmpty) like suggested below
                 .filter(Objects::nonNull)
                 .distinct();
}
Run Code Online (Sandbox Code Playgroud)

可以像这样使用

Stream<String> myStream1DownStream = trimAndFilterOutEmptyStringsAndGetDistinctElements(myStream1);
Stream<String> myStream2DownStream = trimAndFilterOutEmptyStringsAndGetDistinctElements(myStream2);

myStream1DownStream.doOtherStuff();
myStream2DownStream.doSomethingElseStill();
Run Code Online (Sandbox Code Playgroud)

顺便说一句我会用

.filter(Predicate.not(String::isEmpty))  
Run Code Online (Sandbox Code Playgroud)

代替

.map(Strings::emptyToNull)
.filter(Objects::nonNull)
Run Code Online (Sandbox Code Playgroud)

还有一种比较值得质疑的方式,就是使用Lombok的@ExtensionMethod实验性功能。我不会在生产中使用它

然后,您将能够Stream使用自定义方法扩展类的功能

public Stream<String> trimAndFilterOutEmptyStringsAndGetDistinctElements(Stream<String> stream) {
    return stream.map(String::trim)
                 .map(Strings::emptyToNull) // or use not(String::isEmpty) like suggested below
                 .filter(Objects::nonNull)
                 .distinct();
}
Run Code Online (Sandbox Code Playgroud)

用法如下

myStream1.trimAndFilterOutEmptyStringsAndGetDistinctElements()
         .doOtherStuff();
Run Code Online (Sandbox Code Playgroud)

更多信息