流与。 Map 的 entrySet 中的迭代器 - Java 8
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.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 是同一个实例。
不,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()
会给出哈希码。
根据我的理解,下面的代码应该打印 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.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 是同一个实例。
不,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()
会给出哈希码。