Поиск строки в необязательном списке списков - PullRequest
3 голосов
/ 26 февраля 2020

У меня есть список «блоков», которые могут быть нулевыми. Каждый из блоков содержит список имен, которые также могут быть нулевыми. Я пытаюсь найти, является ли какое-либо из имен во всех блоках словом "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 мог вернуть ноль, я должен проверить это в следующем утверждении. Я мог бы обернуть его в другой Optional на тот момент, но тогда я получу Optional<Stream<Optional<List<String>>>>

Использование names -> names != null кажется более чистым? Или есть способ упростить это?

Ответы [ 3 ]

4 голосов
/ 26 февраля 2020

С 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"));
}
2 голосов
/ 26 февраля 2020

Еще один более простой вариант без использования Optional будет просто:

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

Примечание : Одна из ваших проблем - дизайн, где вы говорите, "I иметь список «блоков», который может быть нулевым ", вы должны исправить это, чтобы вернуть пустой список для такого представления, а затем избавиться от проверки null в приведенном выше коде.

2 голосов
/ 26 февраля 2020

Я бы не рекомендовал использовать Optional для null. Вы можете использовать троичный оператор, чтобы проверить, что blocks равно нулю, и просто вернуть false, если оно равно нулю, иначе вывести список blocks и проверить строку

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

Вы также можете добавить простой ноль для существующего кода

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);
}
...