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 ??