2013-02-12 31 views
2

所以,我想製作字符串列表到字符串的映射,但我無法正常工作:ArrayList的HashMap <String>,String無法正常工作?

這是我所做的所有代碼,直到我可以找出原因,我無法進展:

Map<List<String>, String> test = new HashMap<List<String>, String>(); 
test.put(new ArrayList<String>(), "s1"); 
test.put(new ArrayList<String>(), "s2"); 
test.put(new ArrayList<String>(), "s3"); 

System.out.println(test.size()); 

我得到1,應該是3! 爲什麼只有一個對象在我進行3次調用時被添加了3個獨立的對象?我知道意外地將同一對象添加到集合中的危險,但我專門爲每個集合創建了一個新的ArrayList,從而創建了一個全新的對象。

那麼爲什麼Map中只有一個對象呢? 謝謝!

+2

您不應該在HashMap中使用可變鍵。 – 2013-02-12 05:28:33

回答

2

ArrayList#hashCode()對於它們都返回相同的值。如果你看看它的採購:http://grepcode.com/file/repository.grepcode.com/java/root/jdk/openjdk/6-b14/java/util/AbstractList.java#AbstractList.hashCode%28%29

你可以看到,應該沒有元素,或所有相同的元素,哈希碼將是相同的。

解決這個問題,它應該工作正常。以任何方式使用Map或更改hashCode。

+0

謝謝!我該如何更改hashCode? TreeMap會解決這個問題嗎? – 2013-02-12 05:27:03

+0

這會很好。你可以重寫ArrayList並改變hashCode方法。例如,使其具有唯一的ID,例如:創建時間,隨機生成的數字等。 – 2013-02-12 06:35:00

3

試試這個:

Map<String,List<String>> test = new HashMap<String,List<String>>(); 
test.put("s1", new ArrayList<String>()); 
test.put("s2", new ArrayList<String>()); 
test.put("s3", new ArrayList<String>()); 

System.out.println(test.size()); 

注意地圖是key-value關係。出於這個原因,您可能也需要使用String作爲ArrayList作爲,而不是其他方式。這樣,如果添加3個不同的字符串,則每個字符串將具有不同的散列值(散列碼)。因此,您的Map中將有3個不同的密鑰。

還要注意的是:

公共對象放(對象鍵, 對象值)聯營與此映射中的指定鍵指定的值。如果之前的地圖包含此密鑰的映射 ,則舊值爲替換爲

這就是爲什麼你得到1,而不是3,因爲你添加了相同的對象new ArrayList<String>()

看看更詳細的Class HashM規格。

1

您使用ArrayList爲重點,儘量

System.out.println(new ArrayList<String>().equals(new ArrayList<String>())); 

它打印

true 
+0

Equals與哈希碼不同。 – 2013-02-12 06:34:04

+1

hashCode的一般約定是:如果兩個對象根據equals(Object)方法相等,則對這兩個對象中的每一個調用hashCode方法必須產生相同的整數結果。 – 2013-02-12 06:38:39

0

最好的辦法是使用String對象作爲鍵和列表的價值。

看看java文檔說什麼here

如果你想添加ArrayList作爲鍵,那麼覆蓋equals方法就足夠了。

該帖子here給出了很好的見解。我已經從那篇文章中提出了一些我喜歡的東西。

重寫等於兩個的ArrayList:

public boolean equals(List<String> one, List<String> two){ 
    if (one == null && two == null){ 
     return true; 
    } 

    if((one == null && two != null) 
     || one != null && two == null 
     || one.size() != two.size()){ 
     return false; 
    } 

    //to avoid messing the order of the lists we will use a copy 
    //as noted in comments by A. R. S. 
    one = new ArrayList<String>(one); 
    two = new ArrayList<String>(two); 

    Collections.sort(one); 
    Collections.sort(two);  
    return one.equals(two); 
} 
+0

我如何重寫equals方法? – 2013-02-12 05:40:28

+0

但只是再次確認你是否真的需要ArrayList作爲關鍵? – Sam 2013-02-12 06:03:34

0

我不知道爲什麼你需要的資源列表爲鍵和字符串值,但你基本上使用每個把同樣的「鑰匙」因爲哈希碼對於任何空列表都是相同的。與其他答案一樣,最好將列表切換爲值,並將字符串作爲關鍵字。如果列表的變化,在不用彷徨任何未來的嘗試都會返回null

public static void main(String...args) { 
     Map<List<String>, String> test = new HashMap<List<String>, String>(); 
     List<String> bob = new ArrayList<>(); 
     bob.add("asdf"); 
     test.put(new ArrayList<String>(), "s1"); 
     test.put(bob, "s2"); 

     System.out.println(test.size()); 
     System.out.println(test.get(bob)); 
    } 

輸出

2 
s2 

當一個新項目被添加像

public static void main(String...args) { 
     Map<List<String>, String> test = new HashMap<List<String>, String>(); 
     List<String> bob = new ArrayList<>(); 
     bob.add("asdf"); 
     test.put(new ArrayList<String>(), "s1"); 
     test.put(bob, "s2");  
     bob.add("aabbcc"); 

     System.out.println(test.size()); 
     System.out.println(test.get(bob)); 
    } 

的get將無法工作,因爲列表的哈希已經改變。在這種情況下的輸出將是:

2 
null 
相關問題