Получить ключи с наибольшими значениями из хэш-карты?

У меня есть HashMap, как это...

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

Сохраняет имя и имя этого имени. Например...

uniqueNames.put("lastname",42);

Как я могу получить имя с наивысшим результатом?

Для получения дополнительной информации я работаю с деревом двоичного поиска "people", сохраняя уникальные имена и частоты в HashMap. Я хочу, чтобы напечатать наиболее распространенные имена, и кто-то сказал мне использовать HashMap, поскольку я хотел сохранить String вместе с Integer. Может быть, я должен использовать класс для хранения имени и частоты вместо этого? Не могли бы вы предложить некоторые предложения.

Ответ 1

Если вам нужно использовать HashMap, то самый простой способ - это просто перебрать карту в поисках максимального

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,

Ответ 2

Наиболее очевидно, что теперь можно использовать несколько с наибольшим значением вхождения:

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

Другой вариант - использовать Guava BiMap.

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

Ответ 3

Есть два способа обойти это.

Если вы собираетесь делать это часто, я бы предпочел бы сохранить сопоставление в обратном порядке, где ключ - это количество раз, когда имя появилось, а значение - список имен, появившихся много раз. Я бы также использовал 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);
    }
}

Нечто похожее на удаление...

И, наконец, для вашего поиска:

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

Возвращает список имен с максимальными вхождениями.

Если вы сделаете это так, поиск может быть выполнен в O (log n), но требования к пространству увеличиваются (только по постоянному коэффициенту).

Если пробел является проблемой или производительность не является проблемой, просто перейдите через uniqueNames.keySet и отслеживайте максимальный размер.

Ответ 4

Похоже, вы хотите что-то немного похожее на SortedMap, но одно сортируется по значению, а не по ключу. Я не думаю, что такая вещь существует в стандартном API.

Возможно, лучше создать класс 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;
  }

}

Вывод:

Фред: 1
искусство: 3
Берт: 4
боб: 5
Гомер: 5
jim: 10

Ответ 5

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

Ответ 6

Если вам нужно только значение, которое вы можете использовать для этого. В этом примере мне пришлось получить максимальная частота числа среди массива "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);
     }

Ответ 7

Это мой подход.

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

}

Ответ 8

1. Попробуйте это может помочь.

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