java - 在 Java 中,我需要根据值对散列映射的键进行分组

标签 java sorting arraylist grouping top-n

我需要找到前 N 个键。

我有一个作为 HashMap 的输入,其形式为 (key : value):

Banana : 13  
Apple: 12  
Mango : 32  
Orange : 12  
Grape : 18  
Pear : 12  
Peach : 18  

我创建了一个基于值排序的链接 HapMap:

private static <K extends Comparable, V extends Comparable> Map<K, V> sortByValues(Map<K, V> map) {
    List<Map.Entry<K, V>> entries = new LinkedList<Map.Entry<K, V>>(map.entrySet());

    Collections.sort(entries, new Comparator<Map.Entry<K, V>>() {

        @Override
        public int compare(Map.Entry<K, V> o1, Map.Entry<K, V> o2) {
            return o2.getValue().compareTo(o1.getValue());
        }
    });
    Map<K, V> sortedMap = new LinkedHashMap<K, V>();
    for (Map.Entry<K, V> entry : entries) {
        sortedMap.put(entry.getKey(), entry.getValue());
    }
    return sortedMap;
}

这给我的输出是:

Mango : 32  
Grape : 18  
Peach : 18  
Banana : 13  
Apple: 12  
Orange : 12  
Pear : 12  

现在如果我想要前 4 个水果,如果我希望输出是这样的话,我应该如何处理:

Mango :32  
Grape, Peach : 18  
Banana :13  
Apple, Orange, Pear: 12  

我尝试遍历排序后的 hashMap 并比较后续元素的值

int sizeOfMap = myValueSortedMap.size();
ArrayList<String> keyArr = new ArrayList<String>();
int cnt=0,keyVal=0;

while(cnt<(sizeOfMap-1)){

    if(myValueSortedMap.values().toArray()[cnt] == myValueSortedMap.values().toArray()[cnt+1]){

        keyArr.add((String) myValueSortedMap.keySet().toArray()[cnt]+ " , " +(String) myValueSortedMap.keySet().toArray()[cnt+1]);
    }
    else{
        keyArr.add((String) myValueSortedMap.keySet().toArray()[cnt]);
        keyVal = (int) myValueSortedMap.values().toArray()[cnt];
    }
    cnt++;
}

但这并不总是有效。

我想不出解决这个问题的办法。有人可以给我一个线索吗?

最佳答案

您可以使用两步流过程 - 第一步按数值对条目进行分组,第二步对流内容进行排序,应用 4 的限制并打印结果。

map.entrySet()
   .stream()
   .collect(Collectors.groupingBy(Map.Entry::getValue))
   // the map now contains integers mapped to a list of map entries
   .entrySet()
   .stream()
   // sort the stream by descending numeric value
   .sorted((o1, o2) -> o2.getKey().compareTo(o1.getKey()))
   // use the first four elements of the stream
   .limit(4)
   .forEach(entry -> System.out.println(entry.getKey() + " " + entry.getValue().stream().map(Map.Entry::getKey).collect(Collectors.joining(", "))));

这导致

32 Mango
18 Grape, Peach
13 Banana
12 Apple, Pear, Orange

关于java - 在 Java 中,我需要根据值对散列映射的键进行分组,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38180206/

相关文章:

java - 如何更新 ArrayList 的部分元素?

c++ - 在 C++ 中反转二维数组

Ruby - 为什么排序重新排序相等的元素

java - 从字符串数组列表中获取删除和添加的元素

java - MySQL更改为utf8mb4后,Error Unknown character set index for field '224' received from server

arrays - 如何在 Swift 中对字符串的行进行排序?

java - java中如何从hashmap中获取arraylist?

java - Camel Rest 组件是用于设置服务客户端还是服务提供者?

java - 使用锦标赛树查找数组中的第 K 个最大元素

java公共(public)静态最终对象