谓词如何在Java 8中维护状态 [英] How Predicate maintain state in Java 8

查看:50
本文介绍了谓词如何在Java 8中维护状态的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在查看此代码,并试图理解以下代码.

I am looking at this code and trying to understand the following piece of code.

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

BigDecimal totalShare = orders.stream()
    .filter(distinctByKey(o -> o.getCompany().getId()))
    .map(Order::getShare)
    .reduce(BigDecimal.ZERO, BigDecimal::add);

我的问题是每次调用 distinctByKey 并生成新的 ConcurrentHashMap .使用 new ConcurrentHashMap<>(); 吗?

My question here is everytime distinctByKey will be called and resulting new ConcurrentHashMap. how it is maintaining the state using new ConcurrentHashMap<>(); ?

推荐答案

由于这是一个捕获的lambda,实际上,每次调用 distinctByKey时,都会一直返回一个新的 Predicate 实例.;但这会在整个流中发生,而不是在每个单独的元素中发生.

Since this is a capturing lambda, indeed a new Predicate instance will be returned all the time on each call to distinctByKey; but this will happen per entire stream, not per each individual element.

如果您愿意使用以下示例运行示例

If you are willing to run your example with:

Djdk.internal.lambda.dumpProxyClasses =/您的/路径/此处

您会看到为 Predicate 的实现生成了 class .由于这是一个有状态的lambda-它捕获 CHM Function ,因此它将具有 private 构造函数和静态工厂方法返回实例.

you would see that a class is generated for your the implementation of the Predicate. Because this is a stateful lambda - it captures the CHM and Function, it will have a private constructor and a static factory method that returns an instance.

每次对 distinctByKey 的调用都会产生一个不同的实例,但是该实例将被重用于Stream的每个元素.如果运行此示例,事情可能会更加明显:

Each call of distinctByKey will produce a different instance, but that instance will be reused for each element of the Stream. Things might be a bit more obvious if you run this example:

 public static <T> Predicate<T> distinctByKey(Function<? super T,Object> keyExtractor) {
    Map<Object,Boolean> seen = new ConcurrentHashMap<>();
    Predicate<T> predicate =  t -> {
        Object obj = keyExtractor.apply(t);
        System.out.println("stream element : " + obj);
        return seen.putIfAbsent(obj, Boolean.TRUE) == null;
    };

    System.out.println("Predicate with hash :" + predicate.hashCode());
    return predicate;
}

@Getter
@AllArgsConstructor
static class User {
    private final String name;
}

public static void main(String[] args) {
    Stream.of(new User("a"), new User("b"))
          .filter(distinctByKey(User::getName))
          .collect(Collectors.toList());

}

这将输出:

Predicate with hash :1259475182
stream element : a
stream element : b

流的两个元素的单个谓词.

如果添加另一个过滤器:

Stream.of(new User("a"), new User("b"))
      .filter(distinctByKey(User::getName))
      .filter(distinctByKey(User::getName))
      .collect(Collectors.toList());

会有两个谓词:

Predicate with hash :1259475182
Predicate with hash :1072591677
stream element : a
stream element : a
stream element : b
stream element : b

这篇关于谓词如何在Java 8中维护状态的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆