问题 Java如何根据HashMap中的值返回前10个项目


所以我是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

最终结果将是这样的:

十大数字:['27','11','5','8','16','25','1','24','32',   '20']

为了澄清,在Java中我成功创建了一个HashMap,我已经成功检查了数字并增加了键值对的值。我现在卡在排序中并根据值返回前10个数字(键)。


2962
2018-06-13 19:07


起源

有没有理由使用 HashMap,特别是因为你需要排序? - Zong
您是否考虑过使用树形图而不是哈希图? - BlackHatSamurai
可能重复: stackoverflow.com/questions/780541/how-to-sort-hash-map , stackoverflow.com/questions/8119366/sorting-hashmap-by-values - BlackHatSamurai
@TheNewIdiot很好,它对键进行排序,而不是值 - darijan
“基于价值的十大数字”?你什么意思? - fge


答案:


  1. 把地图放 entrySet() 变成一个 List
  2. 使用排序此列表 Collections.sort 和a Comparator 哪种分类 Entry基于他们的价值观。
  3. 使用 subList(int, int) 的方法 List 检索包含前10个元素的新列表。

是的,它会比Python更冗长:)


10
2018-06-13 19:13



是的,这是要走的路。但那么使用的重点是什么 HashMap?特别是当结果被排序时 值?我不知道OP在做什么...... - Zong


使用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));

1
2018-01-22 12:12





HashMaps不是用Java命令的,因此没有一种好的方法可以在没有强力搜索所有键的情况下对它们进行排序。尝试使用 TreeMaphttp://docs.oracle.com/javase/6/docs/api/java/util/TreeMap.html


0
2018-06-13 19:12



TreeMap 根据键而非值来排序。 - arshajii


假设您的地图定义类似于此,并且您希望基于此排序

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));
}

地图中的值实际上没有排序,因为 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 已排序并具有原始映射中的键值对的树,因此您不会丢失信息。


0
2018-06-13 19:11



现在你已经失去了键值配对 - NullUserException
这会按值进行排序,但不会让您轻松查看它们以查看它们引用的键... - chessbot
是的,绑定会丢失,但如果您只需要前10个元素,它就会起作用。 - AnarchoEnte


尝试下一个:

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));
    }

}

0
2018-06-13 19:22



最好使用 b.getValue().compareTo(a.getValue()) 在比较中。 OP的示例使用整数,但如果他们决定放入一些浮点,只需更改类型就会破坏此代码。 - Zong
该 value 是个 声望 一个数字(数字可能是浮动的)。换句话说, 频率。 - Paul Vargas
好吧,我看到在这种情况下它只是整数。但是,我仍然坚持我的建议。 - Zong


番石榴 多集 非常适合您的用例,并且很好地替换您的HashMap。它是一个计算每个元素出现次数的集合。

Multisets有一种方法 copyHighestCountFirst,返回按计数排序的不可变Multiset。

现在一些代码:

Multiset<Integer> counter = HashMultiset.create();
//add Integers 
ImmutableMultiset<Integer> sortedCount = Multisets.copyHighestCountFirst(counter);
//iterate through sortedCount as needed

0
2018-06-13 20:47





用一个 SortedMap,打电话 values()。文档表明以下内容:

The collection's iterator returns the values in ascending order of the corresponding keys

因此,只要您的比较器正确写入,您就可以迭代第一个 n 按键


0
2018-06-13 20:53