问题
To sort it int ascending order I can use:
myMap.entrySet().stream()
.sorted(Map.Entry.comparingByValue())
.collect(Collectors.toMap(Entry::getKey, Entry::getValue));
How can I do it in decreasing order?
回答1:
To sort in reverse order, pass Comparator.reverseOrder()
as parameter to comparingByValue
.
To get a LinkedHashMap
, you must specifically request one with the 4-argument toMap()
. If you don't specify what kind of a map you want, you will get whatever the default is, which currently happens to be a HashMap
. Since HashMap
doesn't preserve the order of elements, it will definitely not do for you.
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
));
With static imports, it becomes a bit more pleasant:
myMap.entrySet().stream()
.sorted(comparingByValue(reverseOrder()))
.collect(toMap(
Map.Entry::getKey,
Map.Entry::getValue,
(x,y)-> {throw new AssertionError();},
LinkedHashMap::new
));
回答2:
You can pass whatever Comparator you wish to comparingByValue
.
For example (I hope I got the syntax right, since I can't test it):
myMap.entrySet().stream()
.sorted(Map.Entry.comparingByValue((v1,v2)->v2.compareTo(v1)))
.collect(Collectors.toMap(Entry::getKey, Entry::getValue));
By comparing the values of the two entries in the opposite order, using the natural ordering (Comparable
's compareTo
), you get a reversed order compared to what comparingByValue()
(which is equivalent to comparingByValue((v1,v2)->v1.compareTo(v2))
) will give you.
BTW, I'm not sure that Collectors.toMap
returns a LinkedHashMap
instance, and even if it currently does, it can change in the future, since the Javadoc doesn't mention it, so you can't rely on it.
To make sure that the resulting Map would be a LinkedHashMap, you should use a different variant of 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));
回答3:
Stream has as sorted
method which accepts a comparator hence you can directly use the comparator as (x,y)->y.getKey().compareTo(x.getKey())
for descending sorting.
To sort the map in ascending we can reverse the ordering as (x,y)->x.getKey().compareTo(y.getKey())
for consolidating result back into LinkedHashMap we can use Collectors toMap(Function<? super T,? extends K> keyMapper, Function<? super T,? extends U> valueMapper, BinaryOperator<U> mergeFunction, Supplier<M> mapSupplier)
which
Returns a Collector that accumulates elements into a Map whose keys and values are the result of applying the provided mapping functions to the input elements.
Working code
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)
)
);
}
}
回答4:
Since Java 1.8 java.util.Comparator.reversed()
myMap.entrySet().stream()
.sorted(Map.Entry.comparingByValue().reversed())
.collect(Collectors.toMap(Entry::getKey, Entry::getValue));
来源:https://stackoverflow.com/questions/29860667/how-to-sort-a-linkedhashmap-by-value-in-decreasing-order-in-java-stream