JAVA 8 distinctByKey

JAVA 8 distinctByKey

提问人:Darkwriter 提问时间:6/10/2022 最后编辑:WJSDarkwriter 更新时间:6/11/2022 访问量:1331

问:

public List<XYZ> getFilteredList(List<XYZ> l1) {
        return l1
                .stream()
                .filter(distinctByKey(XYZ::getName))
                .filter(distinctByKey(XYZ::getPrice))
                .collect(Collectors.toList());
    }

private 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;
    }

谁能帮帮我, 这句话是什么意思------->
return t -> seen.putIfAbsent(keyExtractor.apply(t), Boolean.TRUE) == null;

为什么 lambda 结果与 null 结果相比?

爪哇岛 爪哇-8 轻量级流 API

评论


答:

1赞 WJS 6/10/2022 #1

您的问题围绕以下内容展开:

return t -> seen.putIfAbsent(keyExtractor.apply(t),
                Boolean.TRUE) == null;
  • 首先,返回整个 lambda(从 t->..开始)。它仍然将创建的地图引用为通路,即使地图本身现在超出了范围。closureseen
  • 将通过作为方法引用提供的 setter (keyExtractore.g. XYZ::getName)
  • putIfAbsent尝试将布尔值添加到所提供键的映射中(在本例中为 和 from )。如果键已存在,则返回该值,该值为 。由于不等于 ,因此返回,并且筛选器不传递该值。如果该值不存在,则返回 null。由于为 true,因此将返回并通过过滤器传递的值(即到目前为止它是不同的)。truenamepricekeyExtractortruetruenullfalsenull == nulltrue

下面是其工作原理的示例。这使用简单的记录,并且仅对名称应用筛选器。

record XYZ(String getName, String other){
    @Override
    public String toString() {
        return String.format("[name=%s, other=%s]", getName, other);
    }
}
    
public static void main(String[] args) {
    List<XYZ> l1 = List.of(
            new XYZ("A","B"),
            new XYZ("B","B"),
            new XYZ("B","C"),
            new XYZ("B","D"),
            new XYZ("C","B"));

    
    Object ob =
            l1.stream().filter(distinctByKey(XYZ::getName))
                    .collect(Collectors.toList());
    System.out.println(ob);
}

指纹

[[name=A, other=B], [name=B, other=B], [name=C, other=B]]

请注意,只有第一个 Name of 被允许通过过滤器,其他名称都被阻止了。B

private 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;
}

评论

0赞 BSL 9/11/2022
谢谢你@WJS有用的解释。你能给我一个关于如何对这个函数进行单元测试的想法吗(distinctByKey())?另外,为什么我们在谓词<T>之前有<T>?谢谢。
0赞 WJS 9/11/2022
第二个问题最好在 Java 教程的泛型方法一节中回答。就 Junit 测试而言,一种方法是进行过滤预定义数据结构(例如 )并返回内容的测试。然后,这些内容将与另一个预期结果进行比较,并返回 true 或 false。listlist
0赞 BSL 9/11/2022
非常感谢@WJS的宝贵回答!