2013-01-21 127 views
1

我是Java新手,正在使用本站上的TreeMap代碼示例,但是當我嘗試遍歷TreeMap時,我得到一個空值列表,但是當我直接打印地圖時,可以看到鍵/值對。我該如何糾正這一點?當我從TreeMap打印出值時,爲什麼會得到空值列表?

import java.util.*; 
public class Testing { 

    public static void main(String[] args) { 

     HashMap<String,Double> map = new HashMap<String,Double>(); 
     ValueComparator1 bvc = new ValueComparator1(map); 
     TreeMap<String,Double> sorted_map = new TreeMap<String,Double>(bvc); 

     map.put("A",99.5); 
     map.put("B",67.4); 
     map.put("C",67.4); 
     map.put("D",67.3); 

     System.out.println("unsorted map: "+map); 

     sorted_map.putAll(map); 


     System.out.println("results: "+sorted_map); 

     for(String key: sorted_map.keySet()) 
     { 
      System.out.println(sorted_map.get(key)); //null values-Why? 
     } 
    } 
} 

class ValueComparator1 implements Comparator<String> { 

    Map<String, Double> base; 
    public ValueComparator1(Map<String, Double> base) { 
     this.base = base; 
    } 

    // Note: this comparator imposes orderings that are inconsistent with equals.  
    public int compare(String a, String b) { 
     if (base.get(a) >= base.get(b)) { 
      return -1; 
     } else { 
      return 1; 
     } // returning 0 would merge keys 
    } 
} 

回答

6

它不起作用,因爲當給定相同的鍵時,比較器不返回0,例如,比較(「A」,「A」)。更改爲

public int compare(String a, String b) { 
     Double va = base.get(a); 
     Double vb = base.get(b); 
     if(va > vb) { 
      return -1; 
     } else if(va < vb) { 
      return 1; 
     } else { 
      return a.compareTo(b); 
     } 
    } 

它會工作。

+0

實現那只是需要的東西?因爲在這個例子中我所有的鍵都不同。仍然不明白這個編輯背後的原因。它工作順便。 – lord12

+0

這是必要的,因爲當你調用get(「A」)時,並且地圖查看「A」的條目時,原始比較器說明鍵不相等,所以它不會返回該條目。 –

3

對不起,但你的例子是有點顛倒。您將鍵放入有序映射(樹形圖)中,然後使用這些值作爲鍵,這是您通過值進行比較的意義。看起來您正在尋找處理具有密鑰和值的對象,因此您可能需要考慮以下內容。這肯定是OOP處理「複合」概念的方式,就像你用地圖建模的那樣。

class Pair implements Comparable<Pair> { 
    String value; 
    double key; 

    Pair(String value, double key) { 
     this.value = value; 
     this.key = key; 
    } 

    public int compareTo(Pair p) { 
     return Double.compare(key, p.key); 
    } 

    public String toString(Pair p) { 
     return value + "," + key; 
    } 
} 

static void main(String[] args) { 
    Set<Pair> unsortedSet = new HashSet<Pair>(); 
    unsortedSet.add(new Pair("A", 99.5)); 
    unsortedSet.add(new Pair("B", 67.4)); 
    unsortedSet.add(new Pair("C", 67.4)); 
    unsortedSet.add(new Pair("D", 67.3)); 

    Set<Pair> sortedSet = new TreeSet<Pair>(); 
    sortedSet.add(new Pair("A", 99.5)); 
    sortedSet.add(new Pair("B", 67.4)); 
    sortedSet.add(new Pair("C", 67.4)); 
    sortedSet.add(new Pair("D", 67.3)); 

    System.out.println("Unsorted set: " + unsortedSet); 
    System.out.println("Sorted set: " + sortedSet); 

    for (Pair pair : sortedSet) { 
     System.out.println(pair); 
    } 
} 
1

由於您的比較器永遠不會返回0 TreeMap.get()不起作用。你仍然可以遍歷TreeMap的條目是這樣

for (Entry<String, Double> e : sorted_map.entrySet()) { 
     System.out.println(e); 
    } 

打印

A=99.5 
C=67.4 
B=67.4 
D=67.3 
+0

與equals的一致性當然是理想的,但並不總是需要TreeMap。根據文檔,「即使排序與等號不一致,排序映射的行爲也是明確定義的;它只是不服從Map接口的總體契約。」 –

+0

我同意,將更正我的答案 –

0

亞當Crume的代碼是非常重要的。爲了更好地解釋你,當你打電話給你的sorted_map.get(key)時,它會去java.util.TreeMap class',getEntryUsingComparator方法,因爲你明確地設置了比較器。這種方法看起來像

final Entry<K,V> getEntryUsingComparator(Object key) { 
     K k = (K) key; 
     Comparator<? super K> cpr = comparator; 
     if (cpr != null) { 
      Entry<K,V> p = root; 
      while (p != null) { 
       int cmp = cpr.compare(k, p.key); 
       if (cmp < 0) 
        p = p.left; 
       else if (cmp > 0) 
        p = p.right; 
       else 
        return p; 
      } 
     } 
     return null; 
    } 

由於是在你自己的價值比較compare方法鍵相比,該條目將是無效,因此價值也將是零,因爲map.get作爲

public V get(Object key) { 
     Entry<K,V> p = getEntry(key); 
     return (p==null ? null : p.value); 
    } 
相關問題