[英]Stream Vs. Iterator in entrySet of a Map - Java 8
根据我的理解,以下代码应该打印true
,因为Stream
和Iterator
都指向第一个元素。
但是,当我运行以下代码时,它正在打印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 的相同逻辑条目(其键为“A”,值为“B”)。 但是,它们不是同一个实例。
如果你在Collections.unmodifiableMap(map)
的实现中挖掘得足够深,你会看到迭代Collections.unmodifiableMap(map)
返回的地图的entrySet
返回一个新的Map.Entry
,它包装了原始的可修改条目:
public Map.Entry<K,V> next() {
return new UnmodifiableEntry<>(i.next());
}
我假设在调用set.stream().findFirst().get()
时还会创建一个新实例Map.Entry
实例,因此这两种方法返回不同的实例。
即使您两次调用相同的方法,您也会得到不同的实例,即以下代码也会打印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()
返回相同的实例。
事情是:
Map.Entry<String, String> entry1 = set.iterator().next();
Map.Entry<String, String> entry2 = set.stream().findFirst().get();
您不是在比较放入地图中的值。 但是Entry对象!
换句话说:看起来您的代码正在使用您的代码创建新的Entry 对象。 这完全取决于不可修改的 Map/Set 的内部实现,当它被要求提供迭代器或流时要返回什么......而且因为 Eran 查找起来要快一些:原因是新的Entry 对象是在以下情况下创建的迭代。
因此,当使用equals()
而不是==
...时,您会得到预期的输出。
没有entry1
和entry2
具有相同的值,但它们没有指向同一个对象,因为每次获得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()
将给出哈希码。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.