为什么此lambda表达式在语句中不起作用,而在方法中起作用?

时间:2018-09-04 04:01:37

标签: java lambda stream

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

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 :(得分: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