Je suis en fait capable de trier ma carte
uniquement sur la base de la clé et de la valeur , j'ai même essayé de les trier comme ci-dessous :
J'ai trié les étudiants en fonction du pays, et s'il se trouve que deux étudiants ont les mêmes états
, triez par StudentID
uniquement parmi les pays correspondants. p >
Ce que j'ai essayé jusqu'à présent:
26=Malmo 14=Orebro 110=Orebro 146=Sweden 148=Sweden
Le résultat que j'obtiens ** (résultat réel) **
14=Orebro 26=Malmo 110=Orebro 146=Sweden 148=Sweden
4 Réponses :
Remarque: vos sorties attendues et réelles ne correspondent pas aux clés que vous avez ajoutées à votre Map
.
La raison pour laquelle votre code ne fonctionne pas est que vous vous appelez Stream # sorted
deux fois avec deux Comparator
s séparés, donc le premier appel à Stream # sorted
est inutile dans votre cas (car il est remplacé par le deuxième appel).
J'ai pu obtenir la sortie attendue en passant un comparateur
personnalisé à Stream # sorted
:
6=Malmo 26=Malmo 14=Orebro 110=Orebro 146=Sweden 148=Sweden
Sortie:
Map.Entry.<Integer, String>comparingByValue() .thenComparing(Map.Entry.comparingByKey())
Il y a quelque temps, j'ai répondu à Comment trier le nom avec l'âge en java , De nombreuses similitudes avec votre question en dehors de la structure de données utilisée pour le stockage. Traverser chaque clé et la trier, puis à nouveau en valeur, puis la trier est assez fastidieuse et peut vous rendre très confus. rappelez-vous simplement comment vous aviez l'habitude de parcourir dans Map lorsque vous n'utilisiez pas Stream :
6=Malmo 26=Malmo 14=Orebro 110=Orebro 146=Sweden 148=Sweden
studentMaster.entrySet().stream() .sorted(Comparator.comparing((Map.Entry<Integer, String> m) -> m.getValue()) .thenComparing(Map.Entry::getKey)).forEach(System.out::println);
Sortie
for (Map.Entry<String,String> entry : somemap.entrySet()){..Some Statements..};
Le Comparator
devrait ressembler à ceci:
6=Malmo 26=Malmo 14=Orebro 110=Orebro 146=Sweden 148=Sweden
Et puis le transmettre à la méthode Stream # sorted
: studentMaster .entrySet (). stream (). sorted (comparateur) .forEach (System.out :: println);
Sortie:
Comparator<Entry<Integer, String>> comparator = (o1, o2) -> { int i = o1.getValue().compareTo(o2.getValue()); if (i == 0) { return o1.getKey().compareTo(o2.getKey()); } else { return i; } };
2 façons:
TreeSet
avec Comparable
pojo. TreeSet
avec un comparateur
personnalisé. id = 6, master = Malmo id = 26, master = Malmo id = 14, master = Orebro id = 110, master = Orebro id = 146, master = Sweden id = 148, master = Sweden
TmpComparator.java
( Utilisez TreeSet
avec un Comparator
personnalisé .)
import java.util.*; public class TmpComparator { static Comparator<StudentMaster> smc = new Comparator() { @Override public int compare(Object o1, Object o2) { StudentMaster sm1 = (StudentMaster) o1, sm2 = (StudentMaster) o2; int masterFlag = sm1.master.compareTo(sm2.master); return (masterFlag == 0) ? sm1.id.compareTo(sm2.id) : masterFlag; } }; static class StudentMaster { private Integer id; private String master; public StudentMaster(Integer id, String master) { this.id = id; this.master = master; } @Override public boolean equals(Object o) { StudentMaster osm = (StudentMaster) o; return id == osm.id && master.equals(osm.master); } @Override public int hashCode() { return Objects.hash(id, master); } public String toString() { StringBuilder sb = new StringBuilder(); Formatter fm = new Formatter(sb); fm.format("id = %d, master = %s\n", id, master); fm.close(); return sb.toString(); } } public static void test() { final Set<StudentMaster> smSet = new TreeSet<>(smc); smSet.add(new StudentMaster(146, "Sweden")); smSet.add(new StudentMaster(148, "Sweden")); smSet.add(new StudentMaster(110, "Orebro")); smSet.add(new StudentMaster(6, "Malmo")); smSet.add(new StudentMaster(14, "Orebro")); smSet.add(new StudentMaster(26, "Malmo")); for (StudentMaster sm : smSet) { System.out.print(sm); } } public static void main(String[] args) { test(); } }
Exécutez simplement le main () .
Les résultats des deux sont identiques:
import java.util.*; public class Tmp { static class StudentMaster implements Comparable<StudentMaster> { private Integer id; private String master; public StudentMaster(Integer id, String master) { this.id = id; this.master = master; } @Override public int compareTo(StudentMaster other) { int masterFlag = master.compareTo(other.master); return (masterFlag == 0) ? id.compareTo(other.id) : masterFlag; } @Override public boolean equals(Object o) { StudentMaster osm = (StudentMaster) o; return id == osm.id && master.equals(osm.master); } @Override public int hashCode() { return Objects.hash(id, master); } public String toString() { StringBuilder sb = new StringBuilder(); Formatter fm = new Formatter(sb); fm.format("id = %d, master = %s\n", id, master); fm.close(); return sb.toString(); } } public static void test() { final Set<StudentMaster> smSet = new TreeSet<>(); smSet.add(new StudentMaster(146, "Sweden")); smSet.add(new StudentMaster(148, "Sweden")); smSet.add(new StudentMaster(110, "Orebro")); smSet.add(new StudentMaster(6, "Malmo")); smSet.add(new StudentMaster(14, "Orebro")); smSet.add(new StudentMaster(26, "Malmo")); for (StudentMaster sm : smSet) { System.out.print(sm); } } public static void main(String[] args) { test(); } }
equals ()
doit être amélioré, il s'agit d'une version simplifiée pour le test uniquement.
S'il n'est pas nécessaire de stocker les entrées triées, le comparateur personnalisé devrait suffire
@CaseyRule Je ne crois pas que ce soit un doublon, car l'OP veut trier par valeur puis par clé.
@JacobG. J'avais en fait identifié stackoverflow.com/questions/3074154/... comme dupliquant cette question, mais cette question a été signalée comme un doublon de stackoverflow.com/questions/109383/... . Il semble que la propriété transitive de duplication ne soit pas tenue dans ce cas :)
@CaseyRule Ah, c'est drôle; bonne prise!
votre problème est résolu ou non ??