流与入口中的迭代器映射集 - Java 8

2022-09-02 05:34:58

根据我的理解,下面的代码应该有 print ,因为两者都指向第一个元素。trueStreamIterator

但是,当我运行以下代码时,它正在打印: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);

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


答案 1

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

如果你在 的实现中挖掘得足够深入,你会看到迭代返回的映射返回一个新的,它包装了原始的可修改条目:Collections.unmodifiableMap(map)entrySetCollections.unmodifiableMap(map)Map.Entry

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

我假设在调用 时也会创建一个新的实例实例,因此这两种方法返回不同的实例。Map.Entryset.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);

另一方面,如果您直接从原始条目中获取条目,您将获得:HashMaptrue

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


答案 2

问题是:

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

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

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

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