2011-09-21 9 views
11

Tengo un HashMap definido como esto ...Obtener las claves con los valores más altos de un hashmap?

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

Almacena un nombre, y la aparición de ese nombre. Por ejemplo ...

uniqueNames.put("lastname",42); 

¿Cómo puedo obtener el nombre con mayor frecuencia?

Para algo más de información, estoy trabajando con un árbol de búsqueda binaria de "pueblo", almacenando los nombres únicos y frecuencias en un HashMap. Lo que quiero hacer es imprimir los apellidos más comunes, y alguien me dijo que usara HashMap ya que quería almacenar un String junto con un Integer. ¿Tal vez debería usar una clase para almacenar el nombre y la frecuencia en su lugar? ¿Podría alguien ofrecer algunas sugerencias?

Respuesta

15

Si usted tiene que utilizar un HashMap, a continuación, la forma más sencilla es probabably sólo para recorrer el mapa en busca de la máxima

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

más obvio, ya que permite múltiples con mayor valor de ocurrencia:

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

Otra opción sería usar Guava's BiMap.

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

Utilizando su primer método, ¿cómo podría entonces, teniendo el número del apellido más común, encontrar los últimos apellidos que aparecen tantas veces? Voy a buscar en el otro método, gracias. – steven

+0

El punto es que tiene ** Entrada ** que contiene ** ambos ** el nombre y cuenta con el recuento más alto. –

+0

¿Qué pasa si hay más de una de esas entradas? Guardarlos en una matriz? – steven

1

Hay dos maneras de hacerlo.

Si va a hacer esto con frecuencia, sugeriría almacenar el mapeo al revés, donde la clave es el número de veces que apareció un nombre, y el valor es una lista de nombres que aparecieron muchas veces . También usaría un HashMap para realizar las búsquedas en la otra dirección también.

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

Algo similar para borrar ...

Y, por último, por su búsqueda:

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

devuelve la lista de nombres que tienen las ocurrencias max.

Si lo hace de esta manera, la búsqueda se puede hacer en O (log n) pero los requisitos de espacio aumentan (aunque solo por un factor constante).

Si el espacio es un problema, o el rendimiento no es un problema, simplemente recorra el uniqueNames.keySet y realice un seguimiento del máximo.

+0

¿Qué sucede si hay más de un apellido X veces, cuando X es la frecuencia más grande? – steven

+0

Actualicé la respuesta con código y creo que lo entenderá. No se toma demasiado espacio, ya que casi todas las cosas son punteros de todos modos. –

0

Parece que quiere algo como un SortedMap, pero uno ordenó el valor, no la clave. No creo que exista tal cosa en la API estándar.

En su lugar, sería mejor crear una clase de frecuencia y almacenar instancias en un 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; 
    } 

} 

de salida:

Fred: 1
arte: 3
Bert: 4
bob: 5
cuadrangular: 5
jim: 10

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

Si solo quiere el valor puede ir por esto. En este ejemplo tenía que conseguir la frecuencia máxima de un número de entre una serie de números '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); 
    } 
0

Este es mi enfoque.

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

} 
Cuestiones relacionadas