Stream Vs. Iterator in entrySet of a Map - Java 8

后端 未结 3 1835
轻奢々
轻奢々 2021-02-18 17:10

To my understanding, the following code should have print true, since both Stream and Iterator are pointing to the first element.

相关标签:
3条回答
  • 2021-02-18 17:51

    The thing is:

    Map.Entry<String, String> entry1 = set.iterator().next();
    Map.Entry<String, String> entry2 = set.stream().findFirst().get();
    

    You are not comparing the values you put into the map. But Entry objects!

    In other words: it looks like your code is creating new Entry objects using your code. It is completely up to the internal implementation of that unmodifiable Map/Set what to return when it is asked for an iterator or a stream ... and as Eran was a bit quicker to lookup: the reason is that new Entry objects are created when iterating.

    So, when using equals() instead of == ... you get the expected output.

    0 讨论(0)
  • 2021-02-18 17:58

    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<K,V> 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<String, String> entry1 = set.iterator().next();
    Map.Entry<String, String> 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<String, String> entry1 = map.entrySet ().iterator().next();
    Map.Entry<String, String> 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.

    0 讨论(0)
  • 2021-02-18 18:01

    No both entry1 and entry2 are has same value but they are not pointing the same object because the each time you get the Map.Entry object it create new one.
    Look at the below code :

    import java.util.Collections;
    import java.util.HashMap;
    import java.util.Map;
    import java.util.Set;
    
    public class Test1 {
    
        public static void main(String[] args) {
            final HashMap<String, String> map = new HashMap<>();
            map.put("A", "B");
            final Set<Map.Entry<String, String>> set = Collections.unmodifiableMap(map).entrySet();
            Map.Entry<String, String> entry1 = set.iterator().next();
            Map.Entry<String, String> entry2 = set.stream().findFirst().get();
            System.out.println("entry1 : " + System.identityHashCode(entry1));
            System.out.println("entry2 : " + System.identityHashCode(entry2));
            for (int i = 0; i < 5; i++) {
                System.out.println("directly for set " + i + " : " + System.identityHashCode(set.stream().findFirst().get()));
            }
        }
    }
    

    The output is :

    entry1 : 1283928880
    entry2 : 295530567
    directly for set 0 : 2003749087
    directly for set 1 : 1324119927
    directly for set 2 : 990368553
    directly for set 3 : 1096979270
    directly for set 4 : 1078694789
    

    System.identityHashCode() will give hash code.

    0 讨论(0)
提交回复
热议问题