为什么这个lambda表达式在语句中不起作用,但在方法中工作?

问题描述 投票:-4回答:1

我想要的建议是通过某个内部对象的字段过滤列表。因此我在互联网上找到一种方法,如下所示:

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());

那么结果就是错误。

为什么?这两者有什么不同?

java lambda stream
1个回答
0
投票

在您的第二个代码版本中:

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

地图Map<> seen是为每个元素x初始化的,因此你的过滤器总是返回true,这将让所有元素直通。

Map<> seen声明移动到lambda外部将更正您的使用情况。

在第一个代码版本中,Map<> seen仅初始化为一个。它返回的只是一个谓词:

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

当您将此谓词传递给流时,它不会创建新的Map,而是使用之前声明的引用Map<> seen

© www.soinside.com 2019 - 2024. All rights reserved.