在可选列表列表中查找字符串

Finding string in optional list of lists

我有一个可能为空的 'Blocks' 列表。每个块都包含一个也可以为空的名称列表。我正在尝试查找所有块中的任何名称是否是单词 "blurb".

我有以下有效的代码:

private boolean containsText(List<Blocks> blocks) {
        return Optional.ofNullable(blocks)
            .map(Collection::stream)
            .map(o -> o.map(Blocks::getNames))
            .map(e -> e.anyMatch(names -> names != null && names.contains("blurb")))
            .orElse(false);
}

但由于 getNames 可能 return null 我必须在下一条语句中检查它。那时我可以将它包装在另一个 Optional 中,但是我最终会得到一个 Optional<Stream<Optional<List<String>>>>

使用names -> names != null 看起来更干净?或者有没有办法简化这个?

我不建议使用 Optional 来检查 null 您可以使用三元运算符来检查 blocks 是否为空,如果它是 return false为空,否则流式传输 blocks 列表并检查字符串

return Objects.isNull(blocks) ? false : blocks.stream()
                                             .map(Blocks::getNames)
                                             .filter(Objects::nonNull)
                                             .anyMatch(list->list.contains("blurb"));

您还可以为现有代码添加简单的 null

private boolean containsText(List<Blocks> blocks) {
    return Optional.ofNullable(blocks)
        .map(Collection::stream)
        .map(o -> o.map(Blocks::getNames).filter(Objects::nonNull))
        .map(e -> e.anyMatch(names -> names.contains("blurb")))
        .orElse(false);
}

使用 Java-9 您可以按如下方式使用 Stream.ofNullable

public boolean containsText(List<Blocks> blocks) {
    return Stream.ofNullable(blocks)
            .flatMap(b -> b.stream().map(Blocks::getNames).filter(Objects::nonNull))
            .anyMatch(s -> s.contains("blurb"));
}

不使用 Optional 的另一个更简单的变体就是:

private boolean containsText(List<Blocks> blocks) {
    return blocks != null && blocks.stream()
            .map(Blocks::getNames)
            .filter(Objects::nonNull)
            .anyMatch(list -> list.contains("blurb"));
}

注意:你的问题之一是你所说的设计"I have a list of 'Blocks' that could be null",你应该将其修复为return 一个用于这种表示的空列表,然后去掉上面代码中的 null 检查。