[英]Java How to return top 10 items based on value in a HashMap
所以我对 Java 非常陌生,因此我正在努力通过练习,将我的一个 Python 程序转换为 Java。
我遇到了一个问题,我试图复制行为,从 python 中,以下将只返回排序的键(按值),而不是值:
popular_numbers = sorted(number_dict, key = number_dict.get, reverse = True)
在 Java 中,我做了一些研究,但还没有找到一个足够简单的样本,用于像我这样的 n00b 或类似的方法。 我找到了使用 Guava 进行排序的示例,但排序似乎返回按键排序的 HashMap。
除了上述内容之外,我在 Java 中还没有发现 Python 的其他优点之一是能够轻松返回已排序值的子集。 在 Python 中,我可以简单地执行以下操作:
print "Top 10 Numbers: %s" % popular_numbers[:10]
在这个例子中,number_dict 是一个键值对的字典,其中键代表数字 1..100,值是数字(键)出现的次数:
for n in numbers:
if not n == '':
number_dict[n] += 1
最终结果将是这样的:
前 10 个数字:['27', '11', '5', '8', '16', '25', '1', '24', '32', '20']
澄清一下,在 Java 中我已经成功地创建了一个 HashMap,我已经成功地检查了数字并增加了键值对的值。 我现在被困在排序并根据值返回前 10 个数字(键)。
entrySet()
放入List
。Collections.sort
和Comparator
对这个列表进行排序,该Comparator
根据它们的值对Entry
进行排序。List
的subList(int, int)
方法检索包含前 10 个元素的新列表。是的,它会比 Python 冗长得多:)
使用 Java 8+,获取整数列表的前 10 个元素:
list.stream().sorted().limit(10).collect(Collectors.toList());
要获取地图键的前 10 个元素,即整数:
map.keySet().stream().sorted().limit(10).collect(Collectors.toMap(Function.identity(), map::get));
假设您的地图定义如下,并且您想根据值进行排序:
HashMap<Integer, Integer> map= new HashMap<Integer, Integer>();
//add values
Collection<Integer> values= map.values();
ArrayList<Integer> list= new ArrayList<Integer>(values);
Collections.sort(list);
现在,打印列表的前 10 个元素。
for (int i=0; i<10; i++) {
System.out.println(list.get(i));
}
map 中的值实际上没有排序,因为HashMap
根本没有排序(它根据键的 hashCode 将值存储在桶中)。 此代码仅显示地图中的 10 个最小元素。
编辑排序而不丢失键值对:
//sorted tree map
TreeMap<Integer, Integer> tree= new TreeMap<>();
//iterate over a map
Iteartor<Integer> it= map.keySet().iterator();
while (it.hasNext()) {
Integer key= it.next();
tree.put(map.get(key), key);
}
现在您拥有已排序的TreeMap
树,并且已从原始映射反转键值对,因此您不会丢失信息。
HashMap
在Java 中没有排序,因此没有真正的好方法来对它们进行排序,除非通过所有键进行蛮力搜索。 尝试使用TreeMap
:http ://docs.oracle.com/javase/6/docs/api/java/util/TreeMap.html
尝试下一个:
public static void main(String[] args) {
// Map for store the numbers
Map<Integer, Integer> map = new HashMap<Integer, Integer>();
// Populate the map ...
// Sort by the more popular number
Set<Entry<Integer, Integer>> set = map.entrySet();
List<Entry<Integer, Integer>> list = new ArrayList<>(set);
Collections.sort(list, new Comparator<Entry<Integer, Integer>>() {
@Override
public int compare(Entry<Integer, Integer> a,
Entry<Integer, Integer> b) {
return b.getValue() - a.getValue();
}
});
// Output the top 10 numbers
for (int i = 0; i < 10 && i < list.size(); i++) {
System.out.println(list.get(i));
}
}
Guava Multiset非常适合您的用例,并且可以很好地替换您的 HashMap。 它是一个计算每个元素出现次数的集合。
Multisets有一个方法copyHighestCountFirst ,它返回一个按计数排序的不可变Multiset 。
现在一些代码:
Multiset<Integer> counter = HashMultiset.create();
//add Integers
ImmutableMultiset<Integer> sortedCount = Multisets.copyHighestCountFirst(counter);
//iterate through sortedCount as needed
使用SortedMap
,调用values()
。 文档指出以下内容:
The collection's iterator returns the values in ascending order of the corresponding keys
因此,只要您的比较器写入正确,您就可以遍历前n
键
从密钥集构建一个列表。
使用键按值对 HashMap 进行排序以访问 Collection.sort() 方法中的值。
返回排序键集的子列表。
如果您关心这些值,则可以使用步骤 3 中的键并构建值集。
HashMap<String, Integer> hashMap = new HashMap<String, Integer>(); List list = new ArrayList(hashMap.keySet()); Collections.sort(list, (w1, w2) -> hashMap.get(w2) - hashMap.get(w1)); //按值降序排序;
返回 list.subList(0, 10);
为了保持排名顺序并有效地返回比地图大小小得多的最高计数:
map.entrySet().stream()
.sorted(Map.Entry.comparingByValue(Comparator.reverseOrder()))
.limit(count)
.collect(toMap(Map.Entry::getKey, Map.Entry::getValue,
(e1, e2) -> e1,
LinkedHashMap::new))
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.