2010-06-19 6 views
5

possible en double:
How to sort a Map<Key, Value> on the values in Java?Tri d'un HashMap basé sur la valeur puis la clé?

J'ai un HashMap du type:

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

Le HashMap contient une liste de chaînes et l'entier est un compteur pour la nombre de fois que String a été trouvé. Ce que je voudrais être capable de faire est de trier la HashMap basée sur les entiers, puis sur l'ordre alphabétique des chaînes.

En ce moment je suis tenue d'un registre de la plus grande occurrence d'un mot (variable max nom) et l'affichage des valeurs comme suit:

public void print(){ 
    while(max > 0){ 
     for (String key : h.keySet()){ 
      if(h.get(key) == max){ 
       System.out.println(key + " " + h.get(key)); 
      } 
     } 
     max--; 
    } 
} 

Ce qui ne trie pas les valeurs par ordre alphabétique, aussi les accès le HashMap max * h (taille) fois.

Quelle est la meilleure solution?

+0

@krock bonne trouvaille. Oui, exactement la même question. – cletus

Répondre

3

Regardez Google Guava libraries. Il a un Multiset qui fait le calcul pour vous et vous avez alors la classe Ordering qui simplifie le tri.

Tout ce que vous devez faire est de remplir Multiset avec vos chaînes. Il maintiendra la fréquence pour vous. Ensuite, vous pouvez trier ces chaînes en utilisant Ordering.

1

Probablement pas la solution la plus élégante, mais qu'en est-il de cela?

//TreeSet with reversed natural ordering (big integers first) 
Map<Integer, Set<String>> h = 
    new TreeMap<Integer, Set<String>>(Collections.reverseOrder()); 
//and use TreeSet for the set... 
// ...  
// 
for(Map.Entry<Integer,Set<String>> entry : h.entrySet()){ 
    for(String str : entry.getValue()){ 
     System.out.println(str + " has occured " + entry.getKey() + " times."); 
    } 
} 
+1

'-1 * o1.compareTo (o2)' est défectueux. Considérons le cas où 'compareTo' renvoie' Integer.MIN_VALUE'. –

+0

@Stephen: Merci de m'avoir signalé! –

+0

En fait, je n'aurais pas dû écrire mon propre code pour inverser l'ordre naturel: P Substituer avec la méthode 'Collections.reverseOrder()' .. –

8

Voici une Comparator qui trie Map.Entry objets avec Comparable clés et valeurs:

public class ValueThenKeyComparator<K extends Comparable<? super K>, 
            V extends Comparable<? super V>> 
    implements Comparator<Map.Entry<K, V>> { 

    public int compare(Map.Entry<K, V> a, Map.Entry<K, V> b) { 
     int cmp1 = a.getValue().compareTo(b.getValue()); 
     if (cmp1 != 0) { 
      return cmp1; 
     } else { 
      return a.getKey().compareTo(b.getKey()); 
     } 
    } 

} 

Vous mettiez toutes les entrées de carte dans une liste et puis trier que:

List<Map.Entry<String, Integer>> list = new ArrayList<Map.Entry<String, Integer>>(h.entrySet()); 
Collections.sort(list, new ValueThenKeyComparator<String, Integer>()); 
+0

Presque, je suppose que parce que de cette façon les mots avec moins d'occurrences viennent en premier .. –

-2

vous pouvez utiliser l'interface SortedMap pour trier votre HashMap. C'est très facile - le tri automatique. Voir http://java.sun.com/j2se/1.4.2/docs/api/java/util/SortedMap.html. Je n'ai inclus aucun code ici, mais si vous en avez besoin, ajoutez simplement un commentaire. Je vais vous donner un exemple de code.

+1

- 1, SortedMap trie par clé, plutôt que par valeur – whiskeysierra

+0

Une carte qui garantit en plus qu'elle sera dans l'ordre croissant des clés, triée en fonction de l'ordre naturel de ses clés (voir l'interface Comparable), ou par un comparateur fourni sur la carte triée temps de creation – Vishal

Questions connexes