Bonjour,
J'ai besoin de trier une map sur les valeurs de façon décroissante.
La clé est un String.
La valeur est un Integer.
Comment procéder ?
merci d'avance.
Bonjour,
J'ai besoin de trier une map sur les valeurs de façon décroissante.
La clé est un String.
La valeur est un Integer.
Comment procéder ?
merci d'avance.
En implémentant une classe Comparator comme ceci :
A adapter bien sûr :
Bon courage
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35 public class CollectionComparator { static final Comparator ORDRE_DATE = new Comparator() { public int compare(Object o1, Object o2){ if(!(o1 instanceof Video)) throw new ClassCastException(); return (new Integer(((Video)o1).obtenirAnnee())).compareTo( new Integer(((Video)o2).obtenirAnnee())); } }; static final Comparator ORDRE_REALISATEUR = new Comparator() { public int compare(Object o1, Object o2){ if(!(o1 instanceof Video)) throw new ClassCastException(); return (((Video)o1).obtenirRealisateur()).compareTo( ((Video)o2).obtenirRealisateur()); } }; public static void main(String[] args) { TreeSet t = new TreeSet(); t.add(new Video("Le jour le plus long", "Ken Annakin", 1962)); t.add(new Video("Un pont trop loin", "Richard Attenborough", 1977)); t.add(new Video("Platoon", "Oliver Stone", 1986)); t.add(new Video("Full metal jacket", "Stanley Kubrik", 1987)); t.add(new Video("La ligne rouge", "Terrence Malick", 1998)); t.add(new Video("The patriot", "Roland Emmerich", 2000)); System.out.println("Tri par titre :\n" + t); TreeSet tr = new TreeSet(ORDRE_REALISATEUR); tr.addAll(t); System.out.println("\nTri par réalisateur :\n" + tr); TreeSet ta = new TreeSet(ORDRE_DATE); ta.addAll(t); System.out.println("\nTri par année :\n" + ta); } }
merci pour ta réponse elitost,
Je test ça ce soir.
A noter que la solution que je te donne est à adapter.
Merci elitost,
Ton code m'a bien aidé.
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20 private static Map sortMap(Map aMap) { Map myMap = new HashMap(); TreeSet set = new TreeSet(new Comparator(){ public int compare(Object obj, Object obj1) { Integer val1 = (Integer) ((Map.Entry) obj).getValue(); Integer val2 = (Integer) ((Map.Entry) obj1).getValue(); return val1.compareTo(val2); } }); set.addAll(aMap.entrySet()); for(Iterator it = set.iterator(); it.hasNext() ;) { Map.Entry myMapEntry = (Map.Entry) it.next(); myMap.put(myMapEntry.getKey(), myMapEntry.getValue()); } return myMap; }
C'est bien si ça fonctionne alors.
Bon courage
Bonjour,
J'ai essayé de reprendre votre code car je voudrais trier une Map de façon croissante mais j'ai un petit soucis !!
Voici mon code:
Mon probleme est que les deux lignes suivantes ne me donne pas le même résultat:
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27 private void sortMap(Map aMap) { Map myMap = new HashMap(); Set set = new TreeSet( new Comparator() { public int compare(Object obj, Object obj1) { Integer val1 = (Integer) ((Map.Entry) obj).getValue(); Integer val2 = (Integer) ((Map.Entry) obj1).getValue(); if (val2.compareTo(val1)==0) return -1; return val2.compareTo(val1); } } ); set.addAll(aMap.entrySet()); for(Iterator it = set.iterator(); it.hasNext() ;) { Map.Entry myMapEntry = (Map.Entry) it.next(); System.out.println ( myMapEntry.getKey ( ) + " = " + myMapEntry.getValue ( ) ) ; myMap.put( myMapEntry.getKey(), myMapEntry.getValue()); } System.out.println("MyMap: "+myMap.values()); }
System.out.println (myMapEntry.getKey()+"="+myMapEntry.getValue()) ;
System.out.println("MyMap: "+myMap.values());
En effet, la premiere ligne me donne les résultats dans l'ordre croissant comme je le désire, alors que la deuxieme me donne les résultats dans le sens inverse (en faite elle me donne le résultats toujours dans l'ordre décroissant)
Je ne comprend pas d'ou vient cette erreur. On dirait que la fonction "put" met les réultats toujours dans le même ordre.
Il est également fortement possible que j'ai mal compris le code, en effet je ne suis pas familier avec les comparator.
Pourriez-vous m'aider s'il vous plait.
Merdi beaucoup pour votre aide.
Bonjour,
Moi aussi j'ai essayé le code et ça marche pas est ce que vous pouvez m'aider.
En fait je pense que ça marche que sur le key.
Merci de votre aide.
Bonjour,
J'ai le même problème. J'ai réussi à en résoudre une partie mon problème c'est que dans mon HashMap peux posseder des clés différentes mais les même valeurs du coups votre méthode ne marche plus. Quelqu'un a une idée ??
Voila mon code
Résultat :
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32 import java.util.*; import java.lang.*; public class test { public static void main(String[] args) { Map< String, Integer> tm = new HashMap< String, Integer>(); tm.put("A", new Integer(3)); tm.put("B", new Integer(1)); tm.put("C", new Integer(3)); tm.put("D", new Integer(5)); Map myMap = new HashMap(); TreeSet set = new TreeSet(new Comparator(){ public int compare(Object obj, Object obj1) { Integer val1 = (Integer) ((Map.Entry) obj).getValue(); Integer val2 = (Integer) ((Map.Entry) obj1).getValue(); return val1.compareTo(val2); } }); set.addAll(tm.entrySet()); for(Iterator it = set.iterator(); it.hasNext() ;) { Map.Entry myMapEntry = (Map.Entry) it.next(); System.out.println(myMapEntry.getKey() + " " + myMapEntry.getValue()); myMap.put(myMapEntry.getKey(), myMapEntry.getValue()); } } }
B 1
A 3
D 5
??
Dans ce cas il faut insérer les éléments dans une List au lieu d'un Set.
Et comme une List ne se trie pas toute seule, il faut la faire trier en appelant Collections.sort() en lui passant la List à trier et le Comparator à utiliser.
Je ne suis pas trop d'accord avec les codes précédemment donnés!
Une HashMap est une map non ordonnée, et non triée.
Non ordonnée: quand vous iterez dessus, vous n'êtes pas sur de retrouver les éléments dans le même ordre que celui d'insertion (l'ordre dépend du hashcode des objets)
Non triée: si vous insérez 1 3 6 4 5 6, ils ne seront pas automatiquement ordonnés par valeur croissante/décroissante (ou autre selon le comparator).
Bref si vous utilisez une hashmap en sortie de votre fonction, vous ne pourrez pas être certain de l'ordre!
Votre code devrait marcher avec une Map ordonnée telle que la LinkedHashMap si vous utilisez une:
http://docs.oracle.com/javase/1.4.2/...edHashMap.html
Ca aurait été cool de pouvoir utiliser une TreeMap, qui elle est une map triée, mais seulement sur les clés et non les valeurs...
Le problème est posé depuis longtemps, et il existe plusieurs solutions possibles détaillées ici:
http://stackoverflow.com/questions/1...420912#3420912
C'est mieux qu'une autre Map, mais bon, moi je dis si on veut un ordre précis, on utilise une structure qui conserve cet ordre précis. D'où l'idée de mettre les valeurs dans une List pour avoir les éléments triés dans l'ordre.
Et de garder la Map quand on veut vérifier les associations clé/valeur.
En fait j'avais mal lu le code de elitost/ddams/linchan39 etc et , je pensais qu'ils ajoutaient juste les valeurs dans le set et les triaient pour finir par récupérer la clé associée dans la map (ce qui pose problème si les valeurs ne sont pas uniques forcement...).
Cependant le code suivant n'est pas totalement bon (en plus de ne pas utiliser les générics).
En effet, une fois les map entries triées dans le set, elles sont rajoutées dans une hashmap qui peut potentiellement les réorganiser comme elle veut!)
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 private static Map sortMap(Map aMap) { Map myMap = new HashMap(); TreeSet set = new TreeSet(new Comparator(){ public int compare(Object obj, Object obj1) { Integer val1 = (Integer) ((Map.Entry) obj).getValue(); Integer val2 = (Integer) ((Map.Entry) obj1).getValue(); return val1.compareTo(val2); } }); set.addAll(aMap.entrySet()); for(Iterator it = set.iterator(); it.hasNext() ;) { Map.Entry myMapEntry = (Map.Entry) it.next(); myMap.put(myMapEntry.getKey(), myMapEntry.getValue()); } return myMap; }
Pas du tout
On peut le faire également mais comme tu dis toi même, une liste ne se trie pas toute seule... à la différence d'un SortedSet (TreeSet) qui lui oui et restera toujours ordonné sans avoir besoin d'appeler une méthode.
Bref voici une solution avec les explications dans le code:
Le code executé ici:
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87 public static void main(String[] args) { // If you want to sort a map by value, and if there can be twice the same value: // here is your original map Map<String,Integer> mapToSortByValue = new HashMap<String, Integer>(); mapToSortByValue.put("A", 3); mapToSortByValue.put("B", 1); mapToSortByValue.put("C", 3); mapToSortByValue.put("D", 5); mapToSortByValue.put("E", -1); mapToSortByValue.put("F", 1000); mapToSortByValue.put("G", 79); mapToSortByValue.put("H", 15); // Sort all the map entries by value Set<Map.Entry<String,Integer>> set = new TreeSet<Map.Entry<String,Integer>>( new Comparator<Map.Entry<String,Integer>>(){ @Override public int compare(Map.Entry<String,Integer> obj1, Map.Entry<String,Integer> obj2) { Integer val1 = obj1.getValue(); Integer val2 = obj2.getValue(); // DUPLICATE VALUE CASE // If the values are equals, we can't return 0 because the 2 entries would be considered // as equals and one of them would be deleted (because we use a set, no duplicate, remember!) int compareValues = val1.compareTo(val2); if ( compareValues == 0 ) { String key1 = obj1.getKey(); String key2 = obj2.getKey(); int compareKeys = key1.compareTo(key2); if ( compareKeys == 0 ) { // what you return here will tell us if you keep REAL KEY-VALUE duplicates in your set // if you want to, do whatever you want but do not return 0 (but don't break the comparator contract!) return 0; } return compareKeys; } return compareValues; } } ); set.addAll(mapToSortByValue.entrySet()); // OK NOW OUR SET IS SORTED COOL!!!! // And there's nothing more to do: the entries are sorted by value! for ( Map.Entry<String,Integer> entry : set ) { System.out.println("Set entries: " + entry.getKey() + " -> " + entry.getValue()); } // But if you add them to an hashmap Map<String,Integer> myMap = new HashMap<String,Integer>(); // When iterating over the set the order is still good in the println... for ( Map.Entry<String,Integer> entry : set ) { System.out.println("Added to result map entries: " + entry.getKey() + " " + entry.getValue()); myMap.put(entry.getKey(), entry.getValue()); } // But once they are in the hashmap, the order is not kept! for ( Integer value : myMap.values() ) { System.out.println("Result map values: " + value); } // Also this way doesn't work: // Logic because the entryset is a hashset for hashmaps and not a treeset // (and even if it was a treeset, it would be on the keys only) for ( Map.Entry<String,Integer> entry : myMap.entrySet() ) { System.out.println("Result map entries: " + entry.getKey() + " -> " + entry.getValue()); } // CONCLUSION: // If you want to iterate on a map ordered by value, you need to remember: // 1) Maps are only sorted by keys, so you can't sort them directly by value // 2) So you simply CAN'T return a map to a sortMapByValue function // 3) You can't reverse the keys and the values because you have duplicate values // This also means you can't neither use Guava/Commons bidirectionnal treemaps or stuff like that // SOLUTIONS // So you can: // 1) only sort the values which is easy, but you loose the key/value link (since you have duplicate values) // 2) sort the map entries, but don't forget to handle the duplicate value case (like i did) }
http://www.ideone.com/dq3Lu
Donne en sortie:
Set entries: E -> -1
Set entries: B -> 1
Set entries: A -> 3
Set entries: C -> 3
Set entries: D -> 5
Set entries: H -> 15
Set entries: G -> 79
Set entries: F -> 1000
Added to result map entries: E -1
Added to result map entries: B 1
Added to result map entries: A 3
Added to result map entries: C 3
Added to result map entries: D 5
Added to result map entries: H 15
Added to result map entries: G 79
Added to result map entries: F 1000
Result map values: 5
Result map values: -1
Result map values: 1000
Result map values: 79
Result map values: 3
Result map values: 1
Result map values: 3
Result map values: 15
Result map entries: D -> 5
Result map entries: E -> -1
Result map entries: F -> 1000
Result map entries: G -> 79
Result map entries: A -> 3
Result map entries: B -> 1
Result map entries: C -> 3
Result map entries: H -> 15
Le principal piège ici est de croire qu'une map conserve l'ordre d'insertion.
Et je me suis moi même fait piegé par le return 0 quand on compare 2 int dans le set... du coup les valeurs en double sont effacées du set car on considère que les deux entries comparées sont égales...
Oups pardon, si on veut a tout prix avoir les résultats sous forme de map, il faut ajouter les éléments dans une LinkedHashMap qui conserve l'ordre d'insertion lors de l'itération.
Vous avez un bloqueur de publicités installé.
Le Club Developpez.com n'affiche que des publicités IT, discrètes et non intrusives.
Afin que nous puissions continuer à vous fournir gratuitement du contenu de qualité, merci de nous soutenir en désactivant votre bloqueur de publicités sur Developpez.com.
Partager