Your question revolves about the following:
return t -> seen.putIfAbsent(keyExtractor.apply(t),
Boolean.TRUE) == null;
- first, the return returns the entire lambda (from t->.. onward). It still references the created Map as a
closure
via seen
even though the map itself is now out of scope.
- The
keyExtractor
will retrieve the key (either name or price) in your example via the setters provided as method references (e.g. XYZ::getName
)
putIfAbsent
tries to add the boolean value true
to the map for the supplied key (in this case, the name
and price
from the keyExtractor
). If the key was already present, it returns that value which would be true
. Since true
is not equal to null
, false
is returned and the filter doesn't pass the value. If the value was not there, null is returned. Since null == null
is true, true
will be returned and the value passed thru the filter (i.e. it is thusfar distinct).
Here is an example of how this would work. This uses a simple record and only applying a filter on name.
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);
}
prints
[[name=A, other=B], [name=B, other=B], [name=C, other=B]]
Notice that only the first Name of B
was allowed thru the filter, the others were blocked.
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;
}