почему это лямбда-выражение не работает, когда в заявлении, но работает в методе? - PullRequest
0 голосов
/ 04 сентября 2018

предложение, которое я хотел, это отфильтровать список по полю некоторого внутреннего объекта. таким образом, я нахожу один метод в интернете, например:

public static <T> Predicate<T> distinctByKey(Function<? super T, Object> keyExtractor) {
    Map<Object, Boolean> seen = new ConcurrentHashMap<>();
    return t -> seen.putIfAbsent(keyExtractor.apply(t), Boolean.TRUE) == null;
}

тогда я использую вот так

list.stream().filter(LambdaUtils.distinctByKey(o -> o.getLogisticsNumber() == null ? o.getId() : o.getLogisticsNumber())).collect(Collectors.toList());

это работает правильно, но я хочу попробовать что-то другое, поэтому я изменяю код не используя функцию, а вместо кода. Например:

list.stream().filter(
                    x -> {
                        Map<Object, Boolean> seen = new ConcurrentHashMap<>();
                        Function<DeliveryOrderItemMaterialLogisticInfo ,Object> keyExtractor = o -> o.getLogisticsNumber() == null ? o.getId() : o.getLogisticsNumber();
                        return seen.putIfAbsent(keyExtractor.apply(x), Boolean.TRUE) == null;
                    }
            ).collect(Collectors.toList());

тогда результат - ошибка.

почему? что отличается между этими двумя?

1 Ответ

0 голосов
/ 04 сентября 2018

Во второй версии кода:

Map<Object, Boolean> seen = new ConcurrentHashMap<>();

Карта Map<> seen инициализируется для каждого элемента x, поэтому ваш фильтр всегда возвращает true, что позволит всем элементам проходить.

Переместите декларацию Map<> seen за пределы лямбды, чтобы исправить ваше использование.

В первой версии кода Map<> seen только инициализируется. То, что он возвращает, это просто предикат:

return t -> seen.putIfAbsent(keyExtractor.apply(t), Boolean.TRUE) == null;

Когда вы передаете этот предикат в свой поток, он не создает новый Map, но использует ссылку Map<> seen, объявленную ранее.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...