20

据我了解,以下代码应该有 print 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);

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

4

3 回答 3

33

这两个条目都指的是 Map 的相同逻辑条目(其键是“A”,值是“B”)。但是,它们不是同一个实例。

如果你在实现中挖掘得足够深,Collections.unmodifiableMap(map)你会发现遍历entrySet返回的地图会Collections.unmodifiableMap(map)返回一个新的Map.Entry,它包装了原始的可修改条目:

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

我假设Map.Entry在您调用时还会创建一个新实例实例set.stream().findFirst().get(),因此这两种方法返回不同的实例。

即使您将调用相同的方法两次,您也会得到不同的实例,即以下代码也会打印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()相同的实例。

于 2017-06-22T06:25:55.753 回答
12

事情是:

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

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

换句话说:看起来您的代码正在使用您的代码创建新的Entry 对象。这完全取决于不可修改的 Map/Set 的内部实现,当它被要求提供迭代器或流时要返回的内容......并且 Eran 的查找速度更快:原因是的Entry 对象是在何时创建的迭代

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

于 2017-06-22T06:24:33.937 回答
3

不,两者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()将给出哈希码。

于 2017-06-22T06:44:56.017 回答