由于这是一个捕获 lambda,实际上每次调用 distinctByKey 时都会返回一个新的 Predicate 实例;但这将发生在整个流中,而不是每个单独的元素。
如果您愿意运行您的示例:
Djdk.internal.lambda.dumpProxyClasses=/Your/Path/Here
您会看到为您的Predicate 的实现生成了一个class。因为这是一个有状态的 lambda - 它捕获 CHM 和 Function,所以它将有一个 private 构造函数和一个返回实例的 static factory method。
distinctByKey 的每次调用都会产生一个不同的实例,但该实例将被 Stream 的每个元素重用。如果你运行这个例子,事情可能会更明显:
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
一个Predicate 用于流的两个元素。
如果你添加另一个filter:
Stream.of(new User("a"), new User("b"))
.filter(distinctByKey(User::getName))
.filter(distinctByKey(User::getName))
.collect(Collectors.toList());
会有两个Predicates:
Predicate with hash :1259475182
Predicate with hash :1072591677
stream element : a
stream element : a
stream element : b
stream element : b