原始数据如下所示:
String data = "{ \"a\":1, \"b\":3 , \"c\":-1 }";
我的第一步是将其转换为HashMap:
Gson gson = new Gson();
HashMap<String, Double> map = gson.fromJson(data, HashMap.class);
然后按键值对键进行排序:
public static List<String> sortHashMap(final HashMap<String, Double> map) {
Set<String> set = map.keySet();
List<String> keys = new ArrayList<String>(set);
Collections.sort(keys, new Comparator<String>() {
@Override
public int compare(String s1, String s2) {
if (map.get(s1) < map.get(s2)) {
return 1;
}
return 0;
}
});
return keys;
}
最后,获得前N个键:
keys.subList(0, N);
我终于得到了结果,但我认为这不是一种优雅的方式。
所以我想知道,有没有方便的方法呢?
答案 0 :(得分:5)
更优雅和可扩展的方法是使用优先级队列,其中大小限制为N.使用最小堆优先级队列,我们可以继续向队列添加条目,直到大小达到N.对于每个条目后优先级队列的大小已达到N,将其添加到队列中,然后删除队列头部的元素(具有最小值)。在我们耗尽了HashMap中的所有条目之后,队列将包含前N个条目。
这种方法的优点是,即使整个HashMap无法适应内存,我们也可以将其分解为更小的块并使用这种方法。此外,如果我们有一个并发优先级队列,我们也可以同时从不同的HashMaps向队列中添加条目。
public static List<String> topNKeys(final HashMap<String, Double> map, int n) {
PriorityQueue<String> topN = new PriorityQueue<String>(n, new Comparator<String>() {
public int compare(String s1, String s2) {
return Double.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());
}
答案 1 :(得分:3)
你所做的就是好的;你将不得不在某个地方写一个自定义比较器,你使用它的地方很好。
但您的compare()
方法中有错误:如果s1&gt;您返回0 s2,但是你应该只在数字相等的情况下这样做,如果s1> 1则返回负数。 S2。以下实现纠正了这一点。
更好(更简单)的实现是:
public int compare(String s1, String s2) {
return Double.compare(map.get(s2), map.get(s1)); //reverse order
}