2017-06-22 65 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()會給哈希碼。