当条件涉及可选时,如何避免使用两个过滤器

How do I avoid two filters when condition involves an Optional

我有这样的代码:

myList.stream()
            .filter(item -> item.getName().isPresent())
            .filter(item -> item.getName().get().equalsIgnoreCase(otherName))
            .findFirst();

(... 其中 item.getName() 的 return 类型为 Optional<String>)

如何将两个过滤器压缩为一个?

您可以使用 Optional.filter():

myList.stream()
    .filter(item -> 
        item.getName().filter(n -> n.equalsIgnoreCase(otherName)).isPresent())
    .findFirst();

内部 filter 调用是 Optional.filter,如果不满足过滤条件,returns 为空可选。

我会用“OOP”方式解决它。在 Item 'isNameEqual' 或类似的方法中创建一个方法,该方法将使用可选和忽略大小写隐藏逻辑。

那么你可以只有 1 个过滤器语句 Item::isNameEqual。

你不想在 lambda 中有太多的仪式。

使用逻辑与 (&&) 合并过滤器:

myList.stream()
    .filter(item -> item.getName().isPresent() 
        && item.getName().get().equalsIgnoreCase(otherName))
    .findFirst();

这是安全的,因为如果该值不存在,&& 将短路为 false。

或者使用条件运算符:

myList.stream()
    .filter(item -> item.getName().isPresent()  
        ? item.getName().get().equalsIgnoreCase(otherName)
        : false)
    .findFirst();

另一种方法是使用 null 作为值,如果 Optional<String> 没有值并且 equalsIgnoreCase(null) 将始终 return false:

myList.stream()
    .filter(item -> otherName.equalsIgnoreCase(item
        .getName()
        .orElseGet(null)))
    .findFirst();

你可以用Optional::stream()方法避免它:

If a value is present, returns a sequential Stream containing only that value, otherwise returns an empty Stream.

myList.stream()
  .map(Item::getName)
  .flatMap(Optional::stream)
  .filter(otherName::equalsIgnoreCase)
  .findFirst();