Упростить вложенные лямбда-выражения

2. Упростить вложенные лямбда-выражения

Условие задачи:
Дан код, который ищет пользователей с правом редактирования.

Необходимо:

  • разобраться, что делает метод findEditors();

  • улучшить читаемость кода;

  • уменьшить сложность вложенных лямбда-выражений.

Код:

public class AvoidComplexLambdas {
    private final Set<User> users = new HashSet<>();

    public Set<User> findEditors() {
        return users.stream()
                .filter(u -> u.getRoles().stream()
                        .anyMatch(r -> r.getPermissions().contains(Permission.EDIT)))
                .collect(Collectors.toSet());
    }
}

Спойлеры к решению

Подсказки
💡 Метод оставляет пользователей, у которых хотя бы одна роль содержит разрешение EDIT.
💡 Основная проблема читаемости — вложенная логика внутри filter().
💡 Её можно вынести в отдельный метод с говорящим названием.
💡 После этого в filter() можно использовать ссылку на метод.

Решение

Метод ищет пользователей, у которых есть хотя бы одна роль с разрешением Permission.EDIT.

Вложенную проверку лучше вынести в отдельный метод:

public class AvoidComplexLambdas {
    private final Set<User> users = new HashSet<>();

    public Set<User> findEditors() {
        return users.stream()
                .filter(this::hasEditPermission)
                .collect(Collectors.toSet());
    }

    private boolean hasEditPermission(User user) {
        return user.getRoles().stream()
                .anyMatch(role ->
                        role.getPermissions().contains(Permission.EDIT));
    }
}

Теперь основной метод читается практически как описание бизнес-логики:

.filter(this::hasEditPermission)

Отдельный метод:

private boolean hasEditPermission(User user)

скрывает детали обхода ролей и явно сообщает, что именно проверяется.

Такой рефакторинг:

  • уменьшает вложенность;

  • делает findEditors() проще для чтения;

  • позволяет отдельно тестировать проверку наличия разрешения;

  • упрощает изменение логики проверки в будущем.