如何获得 HashMap 中的 3 个最高值?
How to get the 3 highest values in a HashMap?
我有一个 hashmap 如下:
HashMap<String, Integer> hm = new HashMap<String, Integer>;
hm.put("a", 1);
hm.put("b", 12);
hm.put("c", 53);
hm.put("d", 2);
hm.put("e", 17);
hm.put("f", 8);
hm.put("g", 8);
我如何获得具有 3 个最高值的键?所以它会 return:
"c", "e", "b"
谢谢。
我的解决方案,按值排序并获得前 3 名和 return 键列表。
List<String> keys = hm.entrySet().stream().sorted(Map.Entry.<String, Integer>comparingByValue().reversed()).limit(3).map(Map.Entry::getKey).collect(Collectors.toList());
希望对您有所帮助
这更难阅读,但性能会更好:
public static List<String> firstN(Map<String, Integer> map, int n) {
PriorityQueue<Entry<String, Integer>> pq = new PriorityQueue<>(
n + 1, Map.Entry.comparingByValue()
);
int bound = n + 1;
for (Entry<String, Integer> en : map.entrySet()) {
pq.offer(en);
if (pq.size() == bound) {
pq.poll();
}
}
int i = n;
String[] array = new String[n];
while (--i >= 0) {
array[i] = pq.remove().getKey();
}
return Arrays.asList(array);
}
如果您知道 PriorityQueue
是如何工作的,这就很简单了:它在任何给定时间点只保留 n + 1
个元素。随着元素的添加,最小的元素被一个接一个地移除。
完成后,我们将元素插入到数组中,但顺序相反(因为 PriorityQueue
只保持其头部排序,或者头部始终是 max/min 根据 Comparator
).
您甚至可以使它成为通用的,或者为此创建一个带有流的自定义收集器。
这是我的看法:这只跟踪 TreeSet 中的前 n 个项目。
import java.util.*;
import java.util.stream.Collectors;
public class TopN {
public static <E> Collection<E> topN(Iterable<E> values, Comparator<? super E> comparator, int n) {
NavigableSet<E> result = new TreeSet<>(comparator.reversed());
for (E value : values) {
result.add(value);
if (result.size() > n) {
result.remove(result.last());
}
}
return result;
}
public static void main(String[] args) {
Map<String, Integer> hm = Map.of(
"a", 1,
"b", 12,
"c", 53,
"d", 2,
"e", 17,
"f", 8,
"g", 8);
List<String> result = topN(hm.entrySet(), Map.Entry.comparingByValue(), 3)
.stream()
.map(Map.Entry::getKey)
.collect(Collectors.toList());
System.out.println(result);
}
}
最终输出为[c, e, b]
我有一个 hashmap 如下:
HashMap<String, Integer> hm = new HashMap<String, Integer>;
hm.put("a", 1);
hm.put("b", 12);
hm.put("c", 53);
hm.put("d", 2);
hm.put("e", 17);
hm.put("f", 8);
hm.put("g", 8);
我如何获得具有 3 个最高值的键?所以它会 return:
"c", "e", "b"
谢谢。
我的解决方案,按值排序并获得前 3 名和 return 键列表。
List<String> keys = hm.entrySet().stream().sorted(Map.Entry.<String, Integer>comparingByValue().reversed()).limit(3).map(Map.Entry::getKey).collect(Collectors.toList());
希望对您有所帮助
这更难阅读,但性能会更好:
public static List<String> firstN(Map<String, Integer> map, int n) {
PriorityQueue<Entry<String, Integer>> pq = new PriorityQueue<>(
n + 1, Map.Entry.comparingByValue()
);
int bound = n + 1;
for (Entry<String, Integer> en : map.entrySet()) {
pq.offer(en);
if (pq.size() == bound) {
pq.poll();
}
}
int i = n;
String[] array = new String[n];
while (--i >= 0) {
array[i] = pq.remove().getKey();
}
return Arrays.asList(array);
}
如果您知道 PriorityQueue
是如何工作的,这就很简单了:它在任何给定时间点只保留 n + 1
个元素。随着元素的添加,最小的元素被一个接一个地移除。
完成后,我们将元素插入到数组中,但顺序相反(因为 PriorityQueue
只保持其头部排序,或者头部始终是 max/min 根据 Comparator
).
您甚至可以使它成为通用的,或者为此创建一个带有流的自定义收集器。
这是我的看法:这只跟踪 TreeSet 中的前 n 个项目。
import java.util.*;
import java.util.stream.Collectors;
public class TopN {
public static <E> Collection<E> topN(Iterable<E> values, Comparator<? super E> comparator, int n) {
NavigableSet<E> result = new TreeSet<>(comparator.reversed());
for (E value : values) {
result.add(value);
if (result.size() > n) {
result.remove(result.last());
}
}
return result;
}
public static void main(String[] args) {
Map<String, Integer> hm = Map.of(
"a", 1,
"b", 12,
"c", 53,
"d", 2,
"e", 17,
"f", 8,
"g", 8);
List<String> result = topN(hm.entrySet(), Map.Entry.comparingByValue(), 3)
.stream()
.map(Map.Entry::getKey)
.collect(Collectors.toList());
System.out.println(result);
}
}
最终输出为[c, e, b]