流与。 Map 的 entrySet 中的迭代器 - Java 8

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

根据我的理解,下面的代码应该打印 true,因为 StreamIterator 都指向第一个元素。

但是,当我 运行 以下代码时,它正在打印 false:

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 == entry2);

造成这种不同行为的原因可能是什么?

事情是:

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

您没有比较您放入地图中的 。但是 Entry 个对象!

换句话说:看起来您的代码正在使用您的代码创建 条目对象。这完全取决于 internal 实现不可修改的 Map/Set 当它被要求迭代器或流时要做什么 return ...就像 Eran 一样查找速度更快:原因是 new 条目对象是在 iterating.

时创建的

因此,当使用 equals() 而不是 == 时...您会得到预期的输出。

这两个条目指的是您的地图的同一逻辑条目(其键为 "A",值为 "B")。但是,它们不是同一个实例。

如果您深入研究 Collections.unmodifiableMap(map) 的实现,您会发现迭代 entrySet 地图 return 由 Collections.unmodifiableMap(map) [=38] =] 是一个新的 Map.Entry,它包装了原始的可修改条目:

public Map.Entry<K,V> next() {
  return new UnmodifiableEntry<>(i.next());
}

我假设在调用 set.stream().findFirst().get() 时也创建了一个新实例 Map.Entry 实例,因此这两个方法 return 不同的实例。

即使你调用同一个方法两次你也会得到不同的实例,即下面的代码也会打印 false:

Map.Entry<String, String> entry1 = set.iterator().next();
Map.Entry<String, String> entry2 = set.iterator().next();
System.out.println(entry1 == entry2);

另一方面,如果您直接从原始 HashMap 获取条目,您将得到 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);

如果在这种情况下条目没有被新实例包装,那么 entrySet ().iterator().next()entrySet ().stream().findFirst().get() return 是同一个实例。

不,entry1entry2 都具有相同的值,但它们指向的不是同一个对象,因为每次您获得 Map.Entry 对象时,它都会创建一个新对象。
看下面的代码:

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

输出是:

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()会给出哈希码。