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

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了为什么这个lambda表达式在语句中不起作用,但在方法中工作?相关的知识,希望对你有一定的参考价值。

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

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

那么结果就是错误。

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

答案

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

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

以上是关于为什么这个lambda表达式在语句中不起作用,但在方法中工作?的主要内容,如果未能解决你的问题,请参考以下文章

为啥在未计算的操作数中不允许使用 lambda 表达式,但在常量表达式的未计算部分中允许使用 lambda 表达式?

为啥这个下拉菜单在 IE 中不起作用?

基本的 If else 语句在 javascript 中不起作用

Boost union 在 1.67 中不起作用,但在 1.61 中起作用。为啥?

为啥jquery plusslider在google chrome中不起作用但在firefox中起作用

媒体查询在 chrome 中不起作用,但在 iphone 上起作用