2013-01-07 16 views
4

我目前使用2 for循環來比較所有條目,但我得到重複的比較。因爲HashMaps沒有排序,所以我無法弄清楚如何消除已經做出的比較。例如,我有這樣的:使用Java,如何在不重複比較的情況下將HashMap中的每個條目與同一HashMap中的每個條目進行比較?

for(Entry<String, String> e1: map.entrySet()) 
    { 
     for(Entry<String, String> e2: map.entrySet()) 
     {  
      if (e1.getKey() != e2.getKey()) 
      { 
      //compare e1.getValue() to e2.getValue() 
      } 
     } 
    } 

的問題,這是第一個條目會相比,第二項,然後在第三個項目等。但是,第二項將再次與第一項相比較,等等。然後第三個條目將與第一個條目,第二個條目,第四個條目等進行比較。是否有更好的方法來迭代HashMaps以避免重複比較?

其他信息:

更具體地講,希望回答你的問題,HashMap的我已經是存儲文件的名稱(鍵)和文件內容(值) - 只是文本文件。 HashMap已經通過遍歷一個包含我想要比較的文件的目錄來填充。然後我正在做的是通過一些算法來運行文件對以確定每對文件之間的相似性。我不需要將文件1與文件2進行比較,然後再將文件2與文件1進行比較,因爲我只需要將兩個文件進行一次比較。但我確實需要將每個文件與其他文件進行一次比較。我是使用HashMaps的新品牌。 agim的答案可能只適用於我的目的。但我也會嘗試把我的大腦包圍在Evgeniy Dorofeev和Peter Lawrey的解決方案下面。我希望這有助於更好地解釋事情。

+1

什麼是你想在這裏實現? – mre

+2

更好地得到一個有用的答案,編輯你的問題並解釋**爲什麼**你認爲你需要這樣做,你的最終目標是什麼? –

+0

你是否試圖找到一個值是否在地圖上重複?如果是,您是否需要知道哪些鍵映射到重複的值? – russoue

回答

3

如果你不小心,消除重複不是冗餘的比較,至少在關鍵的成本可能更高的成本。

可以使用System.identityHashCode(x)

for(Map.Entry<Key, Value> entry1: map.entrySet()) { 
    Key key1 = entry1.getKey(); 
    int hash1 = System.identityHashCode(key1); 
    Value value1 = entry1.getValue(); 
    for(Map.Entry<Key, Value> entry2: map.entrySet()) { 
     Key key2 = entry2.getKey(); 
     if (key1 > System.identityHashCode(key2)) continue; 

     Value value2 = entry1.getValue(); 
     // compare value1 and value2; 
    } 
} 
+0

太棒了......非常聰明。 – JimN

+2

@Peter - 我認爲第7行有一個錯字。不應該是'if(hash1> System.identityHashcode(key2))'? – user949300

+1

@ user949300謝謝。它應該是'identityHashCode' –

-1

您可以嘗試使用二維數組結果。如果結果已填充,則不要再次執行比較。這也有存儲結果供以後使用的好處。

因此,對於int結果,您將看到如下所示:Integer[][] results = new Integer[map.entrySet().size()][map.entrySet().size()];這會將數組初始化爲空值,並允許您在比較之前檢查現有結果。這裏需要注意的一點是每個比較結果都應該存儲在數組中兩次,除了比較本身。例如索引1和索引2之間的比較應存儲在results[1][2]result[2][1]中。

希望這會有所幫助。

1

嘗試

HashMap<Object, Object> map = new HashMap<>(); 
    Iterator<Entry<Object, Object>> i = map.entrySet().iterator(); 
    while (i.hasNext()) { 
     Entry next = i.next(); 
     i.remove(); 
     for (Entry e : map.entrySet()) { 
      e.equals(next); 
     } 
    } 

注意,是沒有意義的一個HashMap中比較關鍵,他們總是不相等。也就是說,我們可以遍歷/比較值僅

2

這個怎麼樣的解決方案:

String[] values = map.values().toArray(new String[map.size()]); 
for (int i = 0; i < values.length; i++) { 
    for (int j = i+1; j<values.length; j++) { 
    if (values[i].equals(values[j])) { 
     // ... 
    } 
    } 
} 
+0

該解決方案適用於我。如果我還要創建一個數組來保存這些鍵,這些鍵是否會按照與其數組中存儲的順序相同的順序存儲在它的數組中? – Lani1234

+0

+1。經典而簡單。你也可以使用ArrayList(而不是String [])。即'ArrayList values = new ArrayList(map.values);'然後使用大小並獲取而不是長度和[]。 – user949300

0

順序按鍵如果我理解正確的話,你只是想知道是否有在地圖上的任何值的重複?如果是這樣的:

Set<String> values = new HashSet<String>(map.values()); 
boolean hasDuplicates = values.size() != map.size(); 

這可能更有效率,如果你踢出去,一旦你找到的第一個副本:

Set<String> values = new HashSet<String>(); 
for (String value : map.values()) { 
    if (!values.add(value)) { 
    return true; 
    } 
} 
return false; 
0
public static boolean compareStringHashMaps(Map<String, String> expectedMap, Map<String, String> actualMap) throws Exception 
{ 
    logger.info("## CommonFunctions | compareStringHashMaps() ## "); 
     Iterator iteratorExpectedMap = expectedMap.entrySet().iterator(); 
     Iterator iteratorActualMap = actualMap.entrySet().iterator(); 
     boolean flag = true; 
     while (iteratorExpectedMap.hasNext() && iteratorActualMap.hasNext()){ 
      Map.Entry expectedMapEntry = (Map.Entry) iteratorExpectedMap.next(); 
      Map.Entry actualMapEntry = (Map.Entry) iteratorActualMap.next(); 
      if(!expectedMapEntry.getKey().toString().trim().equals(actualMapEntry.getKey().toString().trim())) 
      { 
       flag = false; 
       break; 
      } 
      else if (!expectedMapEntry.getValue().toString().trim().equals(actualMapEntry.getValue().toString().trim())) 
      { 
       flag = false; 
       break; 
      } 
     } 
     return flag; 

}

+0

這與5個其他4年解決方案有何不同? –

相關問題