例如,如果我有一个包含{"A", 0.0}, {"B", 3.14}, {"C", 3.14}, {"D", 8.8}, {"E", 2.1}, {"F", 1.01}
的地图,并且前3个键将是{"D", "B", "C"}
。
我知道执行此操作的程序方法,但是在Java 8中是否有一种更智能/实用的方法来完成此操作?
编辑:请注意,我们可以将地图的每个元素放入大小为N的优先级队列中,因此时间复杂度应为M log(N),比对所有M个元素(M log(M)。
编辑2:根据要求,这就是我得到的:
public static void main(String args[]) {
final Map<String, Double> map = new HashMap<String, Double>() {{
put("A", 0.0);
put("B", 3.14);
put("C", 3.14);
put("D", 8.8);
put("E", 2.1);
put("F", 1.01);
}};
System.out.println("answer= " + getTopN(map, 3).toString());
}
static List<String> getTopN(final Map<String, Double> map, int n) {
// Creating priority queue with limit size n
PriorityQueue<Entry<String, Double>> pq = new PriorityQueue<>(n, Entry.comparingByValue());
for (Entry<String, Double> entry : map.entrySet()) {
pq.add(entry);
if (pq.size() > n) {
pq.poll();
}
}
Stack<String> stack = new Stack<>();
while (!pq.isEmpty()) {
stack.add(pq.poll().getKey());
}
final ArrayList<String> answer = new ArrayList<>();
while (!stack.isEmpty() && n-- > 0) {
answer.add(stack.pop());
}
return answer;
}
答案 0 :(得分:3)
这是一种通过条目值使用反向Double比较器的方法:
Map<String, Double> map = new HashMap<>();
map.put("A", 0.0);
map.put("B", 3.14);
map.put("C", 3.14);
map.put("D", 8.8);
map.put("E", 2.1);
map.put("F", 1.01);
List<String> topKeys = map.entrySet().stream()
.sorted(Comparator.<Entry<String, Double>>comparingDouble(Entry::getValue)
.reversed())
.limit(3) //limit to 3
.map(Entry::getKey)
.collect(Collectors.toList());
返回的列表包含[D, B, C]
答案 1 :(得分:1)
可以使用TreeSet
(而不是PriorityQueue
和Stack
)来改进您的代码:
static List<String> getTopN(Map<String, Double> map, int n) {
TreeSet<Map.Entry<String, Double>> topN = new TreeSet<>(
Map.Entry.<String, Double>comparingByValue()
.reversed() // by value descending, then by key
.thenComparing(Map.Entry::getKey)); // to allow entries with repeated values
map.entrySet().forEach(e -> {
topN.add(e);
if (topN.size() > n) topN.pollLast();
});
return topN.stream()
.map(Map.Entry::getKey)
.collect(Collectors.toList());
}
请注意,我正在使用一个比较器,该比较器按值降序然后按键对TreeSet
个条目进行排序。这样可以使集合包含相等值的条目。
TreeSet.pollLast()
方法与PriorityQueue.poll()
方法等效。