To my understanding, the following code should have print true, since both Stream and Iterator are pointing to the first element.
However, when I ran the following code it is printing false:
final HashMap map = new HashMap<>();
map.put("A", "B");
final Set> set = Collections.unmodifiableMap(map).entrySet();
Map.Entry entry1 = set.iterator().next();
Map.Entry entry2 = set.stream().findFirst().get();
System.out.println(entry1 == entry2);
What could be the reason for this different behavior?
解决方案
Both entries are referring to the same logical entry of your Map (whose key is "A" and value is "B"). However, they are not the same instance.
If you dig deep enough in the implementation of Collections.unmodifiableMap(map) you'll see that iterating over the entrySet of the map returned by Collections.unmodifiableMap(map) returns a new Map.Entry which wraps the original modifiable entry:
public Map.Entry next() {
return new UnmodifiableEntry<>(i.next());
}
I'm assuming a new instance Map.Entry instance is also created when you call set.stream().findFirst().get(), so the two methods return different instances.
Even if you'll call the same method twice you'll get difference instances, i.e. the following code will also print false:
Map.Entry entry1 = set.iterator().next();
Map.Entry entry2 = set.iterator().next();
System.out.println(entry1 == entry2);
On the other hand, if you obtain the entry directly from the original HashMap, you will get true:
Map.Entry entry1 = map.entrySet ().iterator().next();
Map.Entry entry2 = map.entrySet ().stream().findFirst().get();
System.out.println (entry1==entry2);
If this case the entry is not wrapped by a new instance, so both entrySet ().iterator().next() and entrySet ().stream().findFirst().get() return the same instance.