456 votes

Comment trier les valeurs d'une carte par clé en Java ?

J'ai une carte dont les clés et les valeurs sont des chaînes de caractères.

Les données sont comme les suivants :

"question1", "1"
"question9", "1"
"question2", "4"
"question5", "2"

Je veux trier la carte en fonction de ses clés. Donc, à la fin, je vais avoir question1, question2, question3 .... et ainsi de suite.

En fin de compte, j'essaie de tirer deux cordes de cette carte.

  • Première corde : Questions ( dans l'ordre 1 ..10)
  • Deuxième corde : Réponses (dans le même ordre que la question)

Actuellement, j'ai les éléments suivants :

Iterator it = paramMap.entrySet().iterator();
while (it.hasNext()) {
    Map.Entry pairs = (Map.Entry) it.next();
    questionAnswers += pairs.getKey() + ",";
}

J'obtiens ainsi les questions dans une chaîne, mais elles ne sont pas dans l'ordre.

728voto

Jherico Points 12554

Réponse courte

Utilisez un TreeMap . C'est précisément à cela qu'il sert.

Si cette carte vous est transmise et que vous ne pouvez pas en déterminer le type, vous pouvez procéder comme suit :

SortedSet<String> keys = new TreeSet<>(map.keySet());
for (String key : keys) { 
   String value = map.get(key);
   // do something
}

Cela va itérer à travers la carte dans l'ordre naturel des clés.


Réponse plus longue

Techniquement, vous pouvez utiliser tout ce qui implémente SortedMap mais, sauf dans de rares cas, cela revient à TreeMap tout comme l'utilisation d'un Map La mise en œuvre se résume généralement à HashMap .

Pour les cas où vos clés sont un type complexe qui n'implémente pas Comparable ou si vous ne voulez pas utiliser l'ordre naturel alors TreeMap y TreeSet ont des constructeurs supplémentaires qui vous permettent de passer dans une Comparator :

// placed inline for the demonstration, but doesn't have to be a lambda expression
Comparator<Foo> comparator = (Foo o1, Foo o2) -> {
        ...
    }

SortedSet<Foo> keys = new TreeSet<>(comparator);
keys.addAll(map.keySet());

N'oubliez pas que lorsque vous utilisez un TreeMap o TreeSet qu'il aura des caractéristiques de performance différentes de celles HashMap o HashSet . En gros, les opérations qui trouvent ou insèrent un élément iront de O(1) a O(Log(N)) .

Dans un HashMap le passage de 1 000 à 10 000 éléments n'a pas vraiment d'incidence sur le temps nécessaire à la recherche d'un élément. TreeMap le temps de recherche sera environ 3 fois plus lent (en supposant que Log 2 ). Passer de 1000 à 100 000 sera environ 6 fois plus lent pour chaque recherche d'élément.

1 votes

J'essaie d'utiliser Treemap et de trier les clés des chaînes de caractères en fonction de leur longueur. Je constate que j'obtiens des résultats d'extraction incohérents. Apparemment parce que TreeMap considère un résultat de comparaison de 0 comme "égal" ? Je ne sais pas comment l'utiliser dans ce cas.

2 votes

CompareTo() dont le résultat est 0 est "égal". Si vous écrivez un comparateur qui trie par la longueur des chaînes de caractères, alors vous devez renvoyer une valeur positive ou négative en fonction de la chaîne la plus longue, et ne renvoyer 0 que si les deux chaînes ont la même longueur. Si a et b sont des chaînes de caractères, vous pouvez le faire de la manière suivante : `return a.length() - b.length()' (ou inverser les valeurs si vous voulez les trier dans l'autre sens).

0 votes

Bonjour les gars, si on veut que la carte soit ordonnée par les clés, qui sont ici 1,2,3,4, quel est l'ordre d'insertion.... pourquoi ne pas utiliser LinkedHashSet ? Nous posons simplement les questions une par une, et elles sont ordonnées par l'ordre d'insertion. Quelqu'un peut-il m'aider ?

161voto

TrayMan Points 3586

En supposant que TreeMap n'est pas bon pour vous (et en supposant que vous ne pouvez pas utiliser les génériques) :

List sortedKeys=new ArrayList(yourMap.keySet());
Collections.sort(sortedKeys);
// Do what you need with sortedKeys.

3 votes

Merci. J'avais besoin de faire quelque chose comme ça puisque mes clés étaient de type complexe.

3 votes

Cela ne fera que trier la liste des clés, mais ne triera pas la carte elle-même en fonction des clés. Je cherche également comment trier la carte en fonction des clés et je n'ai pas trouvé de solution. Je vais devoir essayer avec TreeMap je suppose :)

0 votes

SortedKeys.sort() fera l'affaire si vous utilisez java 8+.

79voto

Manoj Singh Points 149

Utilisation de la TreeMap vous pouvez trier la carte.

Map<String, String> map = new HashMap<>();        
Map<String, String> treeMap = new TreeMap<>(map);
for (String str : treeMap.keySet()) {
    System.out.println(str);
}

1 votes

Map<String, List<String>> treeMap = new TreeMap<String, List<String>>(printHashMap) ; for (String str : treeMap.keySet()) { System.out.println(str + " " + treeMap.get(str)) ; }

42voto

AgileJon Points 20497

Utilisez un TreeMap !

32 votes

+1 - Pas assez agile pour battre Jherico, Jon, mais quand même assez bon. 8)

0 votes

Je ne connais pas Java :-( Cela fonctionne à 100%. Beaucoup plus simple que toutes les horribles solutions que j'ai trouvées.

42voto

M-D Points 1279

Si vous avez déjà une carte et que vous souhaitez la trier par touches, il suffit d'utiliser :

Map<String, String> treeMap = new TreeMap<String, String>(yourMap);

Un exemple complet et fonctionnel :

import java.util.HashMap;
import java.util.Set;
import java.util.Map;
import java.util.TreeMap;
import java.util.Iterator;

class SortOnKey {

public static void main(String[] args) {
   HashMap<String,String> hm = new HashMap<String,String>();
   hm.put("3","three");
   hm.put("1","one");
   hm.put("4","four");
   hm.put("2","two");
   printMap(hm);
   Map<String, String> treeMap = new TreeMap<String, String>(hm);
   printMap(treeMap);
}//main

public static void printMap(Map<String,String> map) {
    Set s = map.entrySet();
    Iterator it = s.iterator();
    while ( it.hasNext() ) {
       Map.Entry entry = (Map.Entry) it.next();
       String key = (String) entry.getKey();
       String value = (String) entry.getValue();
       System.out.println(key + " => " + value);
    }//while
    System.out.println("========================");
}//printMap

}//class

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X