2017-06-15 43 views
0

我有一個HashMap resultdata像下面獲取所有前N個等級記錄在java中

"zip000", 1234 
"zip001", 2345 
"zip002", 3456 
"zip003", 4567 
"zip004", 7890 
"zip005", 7890 
"zip006", 123 
"zip007", 234 
"zip010", 7890 
"zip011", 678 
"zip012", 789 
"zip013", 890 

,並使用下面的代碼

public static List<String> topNKeys(final HashMap<String, Integer> map, int n) { 
    PriorityQueue<String> topN = new PriorityQueue<String>(n, new Comparator<String>() { 
     public int compare(String s1, String s2) { 
      return Integer.compare(map.get(s1), map.get(s2)); 
     } 
    }); 

    for(String key:map.keySet()){ 
     if (topN.size() < n) 
      topN.add(key); 
     else if (map.get(topN.peek()) < map.get(key)) { 
      topN.poll(); 
      topN.add(key); 
     } 
    } 
    return (List) Arrays.asList(topN.toArray()); 
} 

上面的代碼顯示我TOPN記錄作爲

假設N = 6

zip001=2345 
zip002=3456 
zip003=4567 
zip005=7890 
zip010=7890 
zip004=7890 

但我需要它t ø給所有頂部6 resultdata根據整數排名,我的意思是像下面

zip013=890 
zip000=1234 
zip001=2345 
zip002=3456 
zip003=4567 
zip005=7890 
zip010=7890 
zip004=7890 

根據其中7890,4567,3456,2345,1234,890是前5整數的整數。

我怎麼能這樣做?任何形式的幫助和建議表示讚賞。

+0

我不明白。根據Integer Rank **,你的意思是**?這個等級是什麼? –

+0

請記住以前的值。如果'key'等於先前的值,則將'n'增加1。 –

+0

@Nico Van Belle這裏根據Integer排名,我的意思是,具有相同值的Integer將被賦予單個排名 – daisy

回答

2

你可以做的兩個步驟:

  1. 收集不同的前N個數字
  2. 收集所有有前N

值在代碼方面的條目,你可以這樣寫:

public static List<Entry<String, Integer>> topNKeys(Map<String, Integer> map, int n) { 
    Set<Integer> topValues = getTopValues(map, n); 
    return getEntriesWithTopValues(map, topValues); 
} 

//Returns the distinct top n values 
private static Set<Integer> getTopValues(Map<String, Integer> map, int n) { 
    TreeSet<Integer> values = new TreeSet<>(map.values()); 
    Set<Integer> topNValues = new HashSet<>(); 
    for (int i = 0; i < n; i++) { 
    Integer v = values.pollLast(); 
    if (v != null) topNValues.add(v); 
    else break; 
    } 
    return topNValues; 
} 

//Returns the entries with a value that is contained in topValues 
private static List<Entry<String, Integer>> getEntriesWithTopValues(Map<String, Integer> map, Set<Integer> topValues) { 
    return map.entrySet().stream() 
      .filter(e -> topValues.contains(e.getValue())) 
      .sorted(Entry.comparingByValue()) 
      .collect(toList()); 
} 

適用於你的例子,它返回所需的輸出噸。

沒有流,最後的方法可以寫成:

private static List<Entry<String, Integer>> getEntriesWithTopValues(Map<String, Integer> map, Set<Integer> topValues) { 
    List<Entry<String, Integer>> result = new ArrayList<>(); 
    for (Entry<String, Integer> e : map.entrySet()) { 
    if (topValues.contains(e.getValue())) result.add(e); 
    } 

    Collections.sort(result, new Comparator<Entry<String, Integer>>() { 
    @Override 
    public int compare(Entry<String, Integer> e1, Entry<String, Integer> e2) { 
     return e1.getValue().compareTo(e2.getValue()); 
    } 
    }); 

    return result; 
} 
+1

這並不能解決問題。 OP需要的限制不是固定的數量,而是固定的不同值。所以結果可能會超過極限,並有一些重複。 – RobCo

+0

@assylias我使用java 7,所以流不可用。你能否請java 7兼容代碼 – daisy

+0

@daisy我已經添加了一個沒有流的版本。 – assylias