2010-11-10 2 views
5

J'ai un HashMap<Object, Student> où l'objet est l'ID de l'étudiant, et l'étudiant est un objet de l'étudiant.Ordre HashMap alphabétiquement par valeur

Comment puis-je utiliser la HashMap par le nom des étudiants, student->getName()?

+0

Il dépend de ce que les devoirs " veut "que vous fassiez. Comme il n'y a pas de «recours», peut-être veut-il que vous montriez/exportiez les étudiants (dans la HashMap) dans un ordre particulier ...de toute façon, les devoirs sont inconstants de cette façon. –

+1

Dupe de http://stackoverflow.com/questions/1894081/what-is-the-easiest-way-to-sort-maps-according-to-values-in-java, http://stackoverflow.com/questions/2839003/trier-dans-hash-maps-in-java et probablement beaucoup plus. – BalusC

+2

Cela doit être l'une des 10 premières questions de Java. –

Répondre

13

Les HashMaps sont intrinsèquement non ordonnées et ne peuvent pas être triées. Au lieu de cela, vous pouvez utiliser une implémentation SortedMap, comme TreeMap.
Cependant, même une carte triée ne peut trier que par ses clés.

Si vous souhaitez trier les valeurs, vous devez les copier dans une liste triée.

0

Les HashMaps ne peuvent pas être triés selon leurs valeurs. Une carte est conçue pour les recherches à temps constant basées sur la clé, donc l'ordre des valeurs ne devrait pas être nécessaire. Si vous avez besoin de trier par nom, je suggère d'utiliser un SortedSet et de créer un comparateur qui trie par les noms.

class StudentComparator implements Comparator<Student> { 
    int compare(Student s1, Student s2) { 
     return s1.getName().compareTo(s2.getName()); 
    } 
} 

Si vous avez besoin à la fois une recherche constante de temps et un ensemble trié par valeur, vous devrez peut-être maintenir une carte et un ensemble.

+0

à moins qu'ils ne soient 'null'. – SLaks

+0

oui, je supposais qu'un étudiant aura toujours un nom –

+1

Et que les étudiants eux-mêmes ne sont pas nulles. – SLaks

1

Les cartes ne peuvent pas être classées par valeurs. Vous pouvez faire cela, cependant:

Collection<Student> students = map.values(); 

Collection.sort(new ArrayList<Student>(students)), new Comparator<Student>() { 
    public int compare(Student s1, Student s2) { 
     return s1.getName().compareTo(s2.getName()); 
    } 
}); 

En supposant, bien sûr, que vous devez itérer sur les valeurs. (Pourquoi autrement voudriez-vous l'ordonner comme ça?)

Bonne chance.

+0

TreeMaps sont commandés. Dire que Maps en général ne peut pas l'être n'est pas complètement précis. Oui, je sais que l'OP a dit d'utiliser un HashMap, mais vous avez dit Map, pas HashMap. –

+1

Commandé par les touches. J'ai dit ordonné par des valeurs, pas des clés. – Todd

0

Je voudrais certainement utiliser une nouvelle classe qui va stocker la clé et l'objet.

Ensuite, vous pouvez placer chaque élément de la Map dans une ArrayList sous la forme de cette classe, et enfin utiliser un comparateur pour trier la ArrayList, ensuite vous construisez simplement une nouvelle Map. Code sera quelque chose comme ceci:

Map<Object, Student> valueMap = new LinkedHashMap<String, String>(); 
List<Student> pairValueList = new ArrayList<PairValue>(); 

PairValue p; 
for (Map.Entry<Object, Student> entry : map.entrySet()) { 
    Object key = entry.getKey(); 
    Student value = entry.getValue();   
    p = new PairValue(key, value); 
    pairValueList.add(p); 
} 

Collections.sort(pairValueList, new Comparator<PairValue>() { 
    @Override 
    public int compare(PairValue c1, PairValue c2) { 
    return c1.getLabel().compareTo(c2.getLabel()); 
    } 
}); 

for (PairValue pv : pairValueList) { 
    valueMap.put(pv.getValue(), pv.getStudent()); 
} 

La classe PairValue

class PairValue {  

    private Object value;  
    private Student student; 

    public PairValue(Object value, String student) { 
    this.value = value; 
    this.student= student; 
    } 

    public String getValue() { 
    return value; 
    } 

    public String getStudent() { 
    return student; 
    }  
} 

Cest la façon dont je résolu un problème similaire, j'ai eu dans le passé. Veuillez noter que l'implémentation de la carte retournée doit être une LinkedHashMap.

4

Vous pourriez ne pas être en mesure de trier une HashMap, mais vous pouvez certainement faire quelque chose qui offre le même effet. J'ai été en mesure de trier ma chaîne < HashMap, entier > par valeur décroissante de l'entier en utilisant l'excellent code affiché sur le blog Javarevisited. Le même principe s'appliquerait à un HashMap < String, String > objet:

/* 
* Java method to sort Map in Java by value e.g. HashMap or Hashtable 
* throw NullPointerException if Map contains null values 
* It also sort values even if they are duplicates 
*/ 
public 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(Entry<K, V> o1, Entry<K, V> o2) { 
      return o1.getValue().compareTo(o2.getValue()); 
      // to compare alphabetically case insensitive return this instead 
      // o1.getValue().toString().compareToIgnoreCase(o2.getValue().toString()); 
     } 
    }); 

    //LinkedHashMap will keep the keys in the order they are inserted 
    //which is currently sorted on natural ordering 
    Map<K,V> sortedMap = new LinkedHashMap<K,V>(); 

    for(Map.Entry<K,V> entry: entries){ 
     sortedMap.put(entry.getKey(), entry.getValue()); 
    } 

    return sortedMap; 
} 

Pour appeler cette méthode, j'utilise:

Map<String, Integer> sorted = sortByValues(myOriginalHashMapObject); 

En savoir plus: http://javarevisited.blogspot.com/2012/12/how-to-sort-hashmap-java-by-key-and-value.html#ixzz2akXStsGj