2014-01-14 14 views
2

我想通過執行這個循環來獲得映像樹的頂部10個元素:TreeMap的<整數,整數>刪除不工作

 TreeMap<Integer, Integer> sortedMap = sortMap(m); 
     String outString = ""; 
     int count = 10; 
     while (count > 0) { 
      count--; 
      Integer k = sortedMap.firstKey(); 
      outString += String.valueOf(k); 
      sortedMap.remove(k); 
      if (count != 0) { 
       outString += ","; 
      } 
     } 

     System.out.println("outVal is " + outVal); 

這將打印outVal is 11377,11377,11377,11377,11377,11377,11377,11377,11377,11377 Integer實現Comparable,那麼,爲什麼不remove在工作嗎?

UPDATE這是我的sortMap實現:

 public static TreeMap<Integer, Integer> sortMap(HashMap<Integer, Integer> map) { 
      ValueComparator bvc = new ValueComparator(map); 
      TreeMap<Integer,Integer> sorted_map = new TreeMap<Integer,Integer>(bvc); 
      sorted_map.putAll(map); 
      return sorted_map; 
     } 

class ValueComparator implements Comparator<Integer> { 
    java.util.Map<Integer, Integer> base; 
    public ValueComparator(java.util.Map<Integer, Integer> base) { 
     this.base = base; 
    } 

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

UPDATE這是有幫助的:Java Map sort by value

+3

你能證明你的'sortMap'方法?我認爲問題在這裏,而不是你提供的代碼片段。 –

+2

'outVal'未在此代碼段中定義。你是不是指'outString'? – dimoniy

+0

我糾正了dimoniy提到的錯誤,輸出在我身邊是正確的。 –

回答

5
public int compare(Integer a, Integer b) { 
    if (base.get(a) >= base.get(b)) { 
     return -1; 
    } else { 
     return 1; 
    } // returning 0 would merge keys 
} 

該比較器(從它是與equals不一致相當開)缺陷,因爲它不滿足其中指出compare(a,b) > 0意味着compare(b,a) < 0反之亦然比較合同。並且由於TreeMap依賴比較器返回0來查找您試圖使用的密鑰remove()它將永遠無法刪除任何內容 - 無論您嘗試使用哪種密鑰,搜索該映射都不會認爲該密鑰存在。

+0

這就是爲什麼這種排序'Map'的方法不可避免地註定要失敗。使用類似http://stackoverflow.com/a/2581754/869736的方法。 –

4

編輯之後,很明顯你的自定義比較器是罪魁禍首。你實際上想要實現的是在地圖中收集十個最高的按鍵。

但是,如果我可以說,你的方法是不必要的迂迴。你已經有了一些地圖m,這是你的出發點。因此,你需要按值僅僅是收集其entrySet,排序,並採取前十位的元素是什麼:

import java.util.Map.Entry; 

final List<Entry<Integer,Integer>> list = new ArrayList<>(m.entrySet()); 
Collections.sort(list, new Comparator<Entry<Integer, Integer>>() { 
    @Override public int compare(Entry<Integer, Integer> o1, Entry<Integer, Integer> o2) { 
    return o1.getValue().compareTo(o2.getValue()); 
    }}); 
final StringBuilder b = new StringBuilder(); 
String delimiter = ""; 
for (Entry<Integer, Integer> e : list.subList(0, 10)) { 
    b.append(delimiter).append(e.getKey()); 
    delimiter = ","; 
} 
System.out.println(b); 

需要注意的是一次性的排序是不是插入一個元素一成二叉搜索樹更有效。

我也在使用StringBuilder,這比在每一步中重新創建完整String效率更高。

+0

根本不需要排序 - [new ArrayList(Collection)](http://docs.oracle.com/javase/7 /docs/api/java/util/ArrayList.html#ArrayList%28java.util.Collection%29)states *按照集合迭代器返回的順序構造一個包含指定集合元素的列表* **。 ** – OldCurmudgeon

+0

@OldCurmudgeon如果_original_'m'已經是'SortedMap'就好了,但是這個問題並不清楚。 –

+1

你可以使用'for(int k:list.subList(0,limit))'來擺脫'if'。 –

0

我試着像下面它爲我工作

TreeMap<Integer, Integer> sortedMap = new TreeMap<>(); 
    String outString = ""; 
    sortedMap.put(1, 10); 
    sortedMap.put(2, 20); 
    sortedMap.put(3, 30); 
    sortedMap.put(4, 40); 
    sortedMap.put(5, 50); 
    int count = 5; 
    while (count > 0) { 
     count--; 
     Integer k = sortedMap.firstKey(); 
     outString += sortedMap.get(k);//String.valueOf(k); 
     sortedMap.remove(k); 
     if (count != 0) { 
      outString += ","; 
     } 
    } 

    System.out.println("outVal is " + outString); 
    System.out.println(sortedMap.size()); 
+0

OP的情況與TreeSet使用自定義比較器不同。 –

+0

謝謝@lan Roberts – Muhammad

+0

我按價值排序,而不是關鍵。 –

相關問題