在 Stream 的处理过程中,我们有时会遇到写 if/else
的情况,而带有 if/else
的逻辑通常会有些长。在写 lambda 表达式时,我们又需要尽量写简洁的语句。那么,对于含有判断语句的情况,该怎么处理?
针对 if/else
通常有以下几种场景:
- if
- if else
- if else if else if else
- 嵌套 if/else
简单 if/else
filter 处理
使用 filter
可以过滤数据,再对过滤出来的数据做处理。过滤时传入的判断条件,对应的正是 if
。
1 2 3 4 5
| public void ifFilterDemo() { List<String> names = Arrays.asList("zhangs", "lis", "wangw", "zhaol"); List<String> newNames = names.stream().filter(s -> s.contains("s")).collect(Collectors.toList()); System.out.println(newNames); }
|
*Match 处理
比如有一个集合,我们循环遍历判断,如果某一条符合条件,直接 return
,否则会处理我们自己的逻辑。
1 2 3 4 5 6 7 8
| public boolean hasElement(List<String> list, String element) { for (String patt : list) { if(MathUtil.match(patt, element)) { return true; } } return false; }
|
这里,其实我们可以简单的用以下语句完成。
1
| return list.parallelStream().anyMatch(pat -> SaFoxUtil.vagueMatch(pat, element));
|
findAny/findFirst 处理
*Match
方法可以简单的处理布尔类型,如果是返回特定值的话,可以借助 findAny/findFirst
。
1 2 3 4 5 6 7 8
| public Token getToken(List<Token> tokenList, String tokenValue) { for (Token token : tokenList) { if (token.getValue().equals(tokenValue)) { return token; } } return null; }
|
以上逻辑也可以使用以下语句简单完成。
1 2 3 4 5
| public Token getToken(List<Token> tokenList, String tokenValue) { return tokenList.stream() .filter(t -> t.getValue().equals(tokenValue)) .findFirst().orElse(null); }
|
参考 Optional 的另一种思路
上面的例子中,我们使用到了 Optional
来处理简单的 if/else
。其实参考这种思想,我们也可以写一个容器类,将 if/else
包装成方法,同时传入一个 Consumer
来执行对应的逻辑。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54
| public class IfElseCondition<T> {
private final T value;
private boolean hit = false;
private IfElseCondition(T value) { this.value = Objects.requireNonNull(value); }
public static <T> IfElseCondition<T> of(T item) { return new IfElseCondition<>(item); }
public IfElseCondition<T> ifTrue(Predicate<T> predicate, Consumer<T> ifConsumer) { if (predicate.test(value)) { hit = true; ifConsumer.accept(value); } return this; }
public IfElseCondition<T> elsif(Predicate<T> predicate, Consumer<T> ifConsumer) { if (!hit && predicate.test(value)) { hit = true; ifConsumer.accept(value); } return this; }
public void otherwise(Consumer<T> elseConsumer) { if (!hit) { elseConsumer.accept(value); } }
public void ifOrOtherwise(Predicate<T> predicate, Consumer<T> ifConsumer, Consumer<T> elseConsumer) { if (predicate.test(value)) { ifConsumer.accept(value); } else { elseConsumer.accept(value); } }
public T getValue() { return value; } }
|
来使用一下:
1 2 3 4 5 6 7 8
| public void ifElseifElseDemo() { List<String> names = Arrays.asList("zhangs", "lis", "wangw", "zhaol"); names.stream().map(IfElseCondition::of).forEach( e -> e.ifTrue(s -> s.contains("s"), s -> System.out.println(s + " contains s")) .elsif(s -> s.length() > 5, s -> System.out.println(s + ".length > 5")) .otherwise(s -> System.out.println(s + " not contains s"))); }
|
程序正常输出:
zhangs contains s
lis contains s
wangwu.length > 5
zhaol not contains s
复杂的逻辑判断
这种情况,真的不建议再用 lambda 来写了。大多数情况下,if/else
真的是很好用的。
总结
- 简单逻辑可以使用
filter
, anyMatch
, allMatch
, noneMatch
, partitioningBy
之类的方法来代替。 - 复杂逻辑不建议使用 lambda 来写,单独抽离出一个方法也许更好,不要太执着。
if/else
大多数情况下直接使用是没问题的。- 可以效仿
Optional
写一个容器工具类来包装 if/else
方法。