简体   繁体   English

从hashmap获取具有最大值的键?

[英]Get the keys with the biggest values from a hashmap?

I have a HashMap defined like this... 我有一个像这样定义的HashMap ......

HashMap<String,Integer> uniqueNames = new HashMap<String,Integer>();

It stores a name, and the occurence of that name. 它存储名称和该名称的出现。 For example... 例如...

uniqueNames.put("lastname",42);

How can I get the name with the highest occurrence? 如何获得出现次数最多的名称?

For some more information, I'm working with a binary search tree of "people", storing the unique names and frequencies in a HashMap . 有关更多信息,我正在使用“people”的二叉搜索树,将唯一的名称和频率存储在HashMap What I want to do is to print the most common last names, and someone told me to use HashMap as I wanted to store a String together with an Integer . 我想要做的是打印最常见的姓氏,有人告诉我使用HashMap因为我想将StringInteger一起存储。 Maybe I should use a class to store the name and frequency instead? 也许我应该使用一个类来存储名称和频率? Could someone please offer some suggestions. 请有人请提供一些建议。

If you have to use a HashMap, then the simplest way is probabably just to loop through the Map looking for the maximum 如果你必须使用HashMap,那么最简单的方法可能就是遍历Map寻找最大值

Entry<String,Integer> maxEntry = null;

for(Entry<String,Integer> entry : uniqueNames.entrySet()) {
    if (maxEntry == null || entry.getValue() > maxEntry.getValue()) {
        maxEntry = entry;
    }
}
// maxEntry should now contain the maximum,

Most obvious, now allowing for multiple with largest occurrence value: 最明显的是,现在允许具有最大出现值的多个:

Integer largestVal = null;
List<Entry<String, Integer>> largestList = new ArrayList<Entry<String, Integer>>();
for (Entry<String, Integer> i : uniqueNames.entrySet()){
     if (largestVal == null || largestVal  < i.getValue()){
         largestVal = i.getValue();
         largestList .clear();
         largestList .add(i);
     }else if (largestVal == i.getValue()){
         largestList .add(i);
     }
}

Another option would be to use Guava's BiMap. 另一种选择是使用Guava的BiMap。

BiMap<String, Integer> uniqueNames = ...;
List<Integer> values = Lists.newArrayList(uniqueNames.values());
Collections.sort(values);
String name = uniqueNames.inverse().get(values.get(0));

There are two ways of going about this actually. 实际上有两种方法可以解决这个问题。

If you are going to be doing this frequently, I would actually suggest storing the mapping in reverse, where the key is the number of times a name has appeared, and the value is a list of names which appeared that many times. 如果您要经常这样做,我实际上建议反向存储映射,其中键是名称出现的次数,值是多次出现的名称列表。 I would also use a HashMap to perform the lookups in the other direction as well. 我也会使用HashMap在另一个方向上执行查找。

TreeMap <Integer, ArrayList <String>> sortedOccurrenceMap =
               new TreeMap <Integer, ArrayList <String>> ();
HashMap <String, Integer> lastNames = new HashMap <String, Integer> ();
boolean insertIntoMap(String key) {
    if (lastNames.containsKey(key)) {
        int count = lastNames.get(key);
        lastNames.put(key, count + 1);

        //definitely in the other map
        ArrayList <String> names = sortedOccurrenceMap.get(count);
        names.remove(key);
        if(!sortedOccurrenceMap.contains(count+1))
            sortedOccurrenceMap.put(count+1, new ArrayList<String>());
        sortedOccurrenceMap.get(count+1).add(key);
    }
    else {
        lastNames.put(key, 1);
        if(!sortedOccurrenceMap.contains(1))
            sortedOccurrenceMap.put(1, new ArrayList<String>());
        sortedOccurrenceMap.get(1).add(key);
    }
}

Something similar for deleting... 删除类似的东西......

And finally, for your search: 最后,为了您的搜索:

ArrayList <String> maxOccurrences() {
    return sortedOccurrenceMap.pollLastEntry().getValue();
}

Returns the List of names that have the max occurrences. 返回具有最大出现次数的名称列表。

If you do it this way, the searching can be done in O(log n) but the space requirements increase (only by a constant factor though). 如果你这样做,搜索可以在O(log n)中完成,但空间要求会增加(尽管只是一个常数因子)。

If space is an issue, or performance isn't a problem, simply iterate through the uniqueNames.keySet and keep track of the max. 如果空间是一个问题,或性能不是问题,只需遍历uniqueNames.keySet并跟踪最大值。

List<String> list= new ArrayList<String>();
    HashMap<String, Integer> map=new HashMap<String,Integer>();

    for(String string: list)
    {
     if(map.containsKey(string))
     {
         map.put(string, map.get(string)+1);
     }
     else {
        map.put(string, 1);
    }
    }


    Entry<String,Integer> maxEntry = null;

    for(Entry<String,Integer> entry : map.entrySet()) {
        if (maxEntry == null || entry.getValue() > maxEntry.getValue()) {
            maxEntry = entry;
        }
    }

If you only want the value you can go for this. 如果你只想要价值,你可以为此而努力。 In this example I had to get the maximum frequency of a number among an array of 'n' numbers 在这个例子中,我必须得到'n'个数组中一个数字的最大频率

      {
        int n = sc.nextInt();
        int arr[] = new int[n];
        int freq = 1;
        int i;
        Map<Integer,Integer> myMap = new HashMap<Integer,Integer>();

        for(i=0;i<n;i++){

            arr[i] = sc.nextInt();
            if(!myMap.containsKey(arr[i])){

                myMap.put(arr[i],freq);

            }
            else
                {

                myMap.put(arr[i],(myMap.get(arr[i])+1));

            }

        }

       int max = 0; 
       for(i=0;i<n;i++){

            if(myMap.get(arr[i])>max)    
            max = myMap.get(arr[i]);

       }
        System.out.println(max);
     }

This is my approach. 这是我的方法。

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.HashMap;
import java.util.Map;
import java.util.Map.Entry;

public class FindWordCounter {

public static void main(String[] args) {
    BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(System.in));

    try {

        System.out.println("Enter the sentence: ");
        String sentence = bufferedReader.readLine();
        FindWordCounter.countWord(sentence);

    }   catch (IOException e) {

        System.out.println(e);

    }
}

public static void countWord(String sentence) {

    Map<String, Integer> hashMap = new HashMap<String, Integer>();
    String[] word = sentence.toLowerCase().split(" ");

    for (int i=0; i<word.length; i++) {

        if (hashMap.containsKey(word[i])) {

            int count = hashMap.get(word[i]);
            hashMap.put(word[i], count + 1);

        }
        else {
            hashMap.put(word[i], 1);
        }
    }

    Entry<String,Integer> maxCount = null;

    for(Entry<String,Integer> entry : hashMap.entrySet()) {

        if (maxCount == null || entry.getValue() > maxCount.getValue()) {
            maxCount = entry;

        }
    }

    System.out.println("The word with maximum occurence is: " + maxCount.getKey() 
                            + " and the number of occurence is: " + maxCount.getValue());
}

}

1.Try this it may help. 试试这可能有所帮助。

static <K, V> List<K> getAllKeysForValue(Map<K, V> mapOfWords, V value) 
{
    List<K> listOfKeys = null;

    //Check if Map contains the given value
    if(mapOfWords.containsValue(value))
    {
        // Create an Empty List
        listOfKeys = new ArrayList<>();

        // Iterate over each entry of map using entrySet
        for (Map.Entry<K, V> entry : mapOfWords.entrySet()) 
        {
            // Check if value matches with given value
            if (entry.getValue().equals(value))
            {
                // Store the key from entry to the list
                listOfKeys.add(entry.getKey());
            }
        }
    }
    // Return the list of keys whose value matches with given value.
    return listOfKeys;  
}

Seems like you want something a bit like a SortedMap but one sorted on the value, not the key. 看起来你想要的东西有点像SortedMap但是一个按照值排序,而不是键。 I don't think such a thing exists in the standard API. 我不认为标准API中存在这样的事情。

It might be better to create a Frequency class and store instances in a SortedSet instead. 最好创建一个Frequency类并将实例存储在SortedSet

import java.util.Set;
import java.util.TreeSet;

public class Frequency implements Comparable<Frequency> {

  private String name;
  private int freq;

  public Frequency(String name, int freq) {
    this.name = name;
    this.freq = freq;
  }

  public static void main(String[] args) {
    Set<Frequency> set = new TreeSet<Frequency>();

    set.add(new Frequency("fred", 1));
    set.add(new Frequency("bob", 5));
    set.add(new Frequency("jim", 10));
    set.add(new Frequency("bert", 4));
    set.add(new Frequency("art", 3));
    set.add(new Frequency("homer", 5));

    for (Frequency f : set) {
      System.out.println(f);
    }
  }

  @Override
  public boolean equals(Object o) {
    if (o == null) return false;
    if (o.getClass().isAssignableFrom(Frequency.class)) {
      Frequency other = (Frequency)o;
      return other.freq == this.freq && other.name.equals(this.name);
    } else {
      return false;
    }
  }

  @Override
  public int compareTo(Frequency other) {
    if (freq == other.freq) {
      return name.compareTo(other.name);
    } else {
      return freq - other.freq;
    }
  }

  @Override
  public String toString() {
    return name + ":" + freq;
  }

}

Output: 输出:

fred:1 弗雷德:1
art:3 艺术:3
bert:4 BERT:4
bob:5 鲍勃:5
homer:5 本垒打:5
jim:10 吉姆:10

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM