Comment trier un LinkedHashMap par valeur en ordre décroissant dans java stream?
faire le tri int ordre croissant, je peux utiliser:
myMap.entrySet().stream()
.sorted(Map.Entry.comparingByValue())
.collect(Collectors.toMap(Entry::getKey, Entry::getValue));
Comment puis-je le faire en ordre décroissant?
4 réponses
Depuis Java 1.8 java.util.Comparateur.inversé()
myMap.entrySet().stream()
.sorted(Map.Entry.comparingByValue().reversed())
.collect(Collectors.toMap(Entry::getKey, Entry::getValue));
Pour trier dans l'ordre inverse, pass Comparator.reverseOrder()
comme paramètre comparingByValue
.
Pour obtenir un LinkedHashMap
, vous devez en demander un avec le 4-argument toMap()
. Si vous ne spécifiez pas le type de carte que vous voulez, vous obtiendrez ce que la valeur par défaut est, ce qui se trouve être un HashMap
. Depuis HashMap
ne préserve pas l'ordre des éléments, il ne fera certainement pas pour vous.
myMap.entrySet().stream()
.sorted(Map.Entry.comparingByValue(Comparator.reverseOrder()))
.collect(Collectors.toMap(
Map.Entry::getKey,
Map.Entry::getValue,
(x,y)-> {throw new AssertionError();},
LinkedHashMap::new
));
avec les importations statiques, il devient un peu plus agréable:
myMap.entrySet().stream()
.sorted(comparingByValue(reverseOrder()))
.collect(toMap(
Map.Entry::getKey,
Map.Entry::getValue,
(x,y)-> {throw new AssertionError();},
LinkedHashMap::new
));
vous pouvez passer n'importe quel comparateur que vous voulez comparingByValue
.
Par exemple (j'espère que je suis la syntaxe droit, puisque je ne peux pas tester):
myMap.entrySet().stream()
.sorted(Map.Entry.comparingByValue((v1,v2)->v2.compareTo(v1)))
.collect(Collectors.toMap(Entry::getKey, Entry::getValue));
En comparant les valeurs des deux entrées dans l'ordre inverse, à l'aide de l'ordre naturel (Comparable
compareTo
), vous obtenez un ordre inversé par rapport à ce comparingByValue()
(ce qui équivaut à comparingByValue((v1,v2)->v1.compareTo(v2))
).
BTW, je ne suis pas sûr que Collectors.toMap
retourne un LinkedHashMap
exemple, et même si elle actuellement cela peut changer dans le futur, puisque le Javadoc ne le mentionne pas, donc vous ne pouvez pas compter dessus.
pour être sûr que la carte résultante soit une LinkedHashMap, vous devez utiliser une variante différente de toMap:
myMap.entrySet().stream()
.sorted(Map.Entry.comparingByValue((v1,v2)->v2.compareTo(v1)))
.collect(Collectors.toMap(Entry::getKey, Entry::getValue, (v1,v2)->v1, LinkedHashMap::new));
Stream sorted
méthode qui accepte un comparateur d'où vous pouvez directement utiliser le comparateur comme (x,y)->y.getKey().compareTo(x.getKey())
pour le tri décroissant.
Pour trier la carte dans ascending nous pouvons inverser l'ordre comme (x,y)->x.getKey().compareTo(y.getKey())
pour consolider le résultat dans LinkedHashMap nous pouvons utiliser des collecteurs toMap(Function<? super T,? extends K> keyMapper, Function<? super T,? extends U> valueMapper, BinaryOperator<U> mergeFunction, Supplier<M> mapSupplier)
qui
Renvoie un collecteur qui accumule des éléments dans une carte dont les clés et les valeurs sont le résultat de l'application des fonctions de mappage fournies à l'entrée élément.
code de travail
import java.io.*;
import java.util.*;
import java.util.function.*;
import java.util.stream.Collectors;
import java.util.stream.*;
public class HelloWorld{
public static void main(String []args){
LinkedHashMap<Integer,Integer> hashMap = new LinkedHashMap<Integer,Integer>();
hashMap.put(1,5);
hashMap.put(7,9);
hashMap.put(3,8);
hashMap.put(10,5);
Function<Map.Entry<Integer,Integer>,Integer> keyMapper = x->x.getKey();
Function<Map.Entry<Integer,Integer>,Integer> valueMapper = x->x.getValue();
BinaryOperator< Integer> mergeFunction = (x,y)->x;// we do not want any merging here
Supplier<LinkedHashMap<Integer,Integer>> mapRequired =()-> {return new LinkedHashMap<Integer,Integer>();};// to maintain order we must use LinkedHashMap
Comparator<Map.Entry<Integer,Integer>> descendingComparator = (x,y)->y.getKey().compareTo(x.getKey());
// we can write it as
System.out.println(
hashMap.entrySet().stream()
.sorted (descendingComparator)
.collect(Collectors.toMap(
keyMapper,
valueMapper,
mergeFunction,
mapRequired)
)
);
// or even by writing below will also work
System.out.println(
hashMap.entrySet().stream()
.sorted ((x,y)->y.getKey().compareTo(x.getKey()))
.collect(Collectors.toMap(
x->x.getKey(),
x->x.getValue(),
(x,y)->x,
LinkedHashMap::new)
)
);
}
}