2017-06-22 67 views
20

据我的理解,下面的代码应该打印true,因为StreamIterator都指向第一个元素。Stream与集合中的迭代器

然而,当我运行下面的代码是打印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); 
+6

不,他们不应该,因为HashMap的entrySet没有排序。 –

+3

@ JBNizet--同意,但我的地图中只有1个元素。 –

+14

地图也不保证它们不会即时创建新的Map.Entry实例。不要用==比较对象。使用equals()。 –

回答

33

这两个条目都指的是您的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()返回的S一个例子。

+2

在next()中找到该行的荣誉。我也做了一些搜索,但很快就放弃了。修正了杂乱的缩进btw ;-) – GhostCat

+2

伟大的发现。似乎这个问题与stream vs iterator无关,但是它与不可修改的映射实现有关。 – GaurZilla

12

的事情是:

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

你是不是比较你把地图中的值。但是条目对象!

换句话说:它看起来像您的代码正在创建使用您的代码的条目对象。这完全取决于内部实现该不可修改的Map/Set时要求什么时候返回一个迭代器或一个流...并且因为Eran查找起来有点快:原因是条目当迭代时创建对象。

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

2

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