我对Java比较陌生,经常发现需要对值进行Map<Key,Value>排序。
由于这些值不是唯一的,我发现自己将keySet转换为一个数组,并使用自定义比较器通过数组排序对该数组进行排序,该比较器根据与该键关联的值进行排序。
有没有更简单的方法?
我对Java比较陌生,经常发现需要对值进行Map<Key,Value>排序。
由于这些值不是唯一的,我发现自己将keySet转换为一个数组,并使用自定义比较器通过数组排序对该数组进行排序,该比较器根据与该键关联的值进行排序。
有没有更简单的方法?
当前回答
最佳方法
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.Map.Entry;
public class OrderByValue {
public static void main(String a[]){
Map<String, Integer> map = new HashMap<String, Integer>();
map.put("java", 20);
map.put("C++", 45);
map.put("Unix", 67);
map.put("MAC", 26);
map.put("Why this kolavari", 93);
Set<Entry<String, Integer>> set = map.entrySet();
List<Entry<String, Integer>> list = new ArrayList<Entry<String, Integer>>(set);
Collections.sort( list, new Comparator<Map.Entry<String, Integer>>()
{
public int compare( Map.Entry<String, Integer> o1, Map.Entry<String, Integer> o2 )
{
return (o1.getValue()).compareTo( o2.getValue() );//Ascending order
//return (o2.getValue()).compareTo( o1.getValue() );//Descending order
}
} );
for(Map.Entry<String, Integer> entry:list){
System.out.println(entry.getKey()+" ==== "+entry.getValue());
}
}}
输出
java ==== 20
MAC ==== 26
C++ ==== 45
Unix ==== 67
Why this kolavari ==== 93
其他回答
对于Java 8,您可以使用streams api以一种明显不那么冗长的方式来实现:
Map<K, V> sortedMap = map.entrySet().stream()
.sorted(Entry.comparingByValue())
.collect(Collectors.toMap(Entry::getKey, Entry::getValue, (e1, e2) -> e1, LinkedHashMap::new));
要使用Java 8中的新功能实现这一点,请执行以下操作:
import static java.util.Map.Entry.comparingByValue;
import static java.util.stream.Collectors.toList;
<K, V> List<Entry<K, V>> sort(Map<K, V> map, Comparator<? super V> comparator) {
return map.entrySet().stream().sorted(comparingByValue(comparator)).collect(toList());
}
条目使用给定的比较器按其值排序。或者,如果您的值可以相互比较,则不需要显式比较器:
<K, V extends Comparable<? super V>> List<Entry<K, V>> sort(Map<K, V> map) {
return map.entrySet().stream().sorted(comparingByValue()).collect(toList());
}
返回的列表是调用此方法时给定映射的快照,因此两者都不会反映对另一个的后续更改。对于地图的实时可迭代视图:
<K, V extends Comparable<? super V>> Iterable<Entry<K, V>> sort(Map<K, V> map) {
return () -> map.entrySet().stream().sorted(comparingByValue()).iterator();
}
返回的可迭代对象在每次迭代时都会创建给定映射的新快照,因此除非并发修改,否则它将始终反映映射的当前状态。
在Java 8及以上版本中对任何地图进行排序的简单方法
Map<String, Object> mapToSort = new HashMap<>();
List<Map.Entry<String, Object>> list = new LinkedList<>(mapToSort.entrySet());
Collections.sort(list, Comparator.comparing(o -> o.getValue().getAttribute()));
HashMap<String, Object> sortedMap = new LinkedHashMap<>();
for (Map.Entry<String, Object> map : list) {
sortedMap.put(map.getKey(), map.getValue());
}
如果您使用的是Java 7及以下版本
Map<String, Object> mapToSort = new HashMap<>();
List<Map.Entry<String, Object>> list = new LinkedList<>(mapToSort.entrySet());
Collections.sort(list, new Comparator<Map.Entry<String, Object>>() {
@Override
public int compare(Map.Entry<String, Object> o1, Map.Entry<String, Object> o2) {
return o1.getValue().getAttribute().compareTo(o2.getValue().getAttribute());
}
});
HashMap<String, Object> sortedMap = new LinkedHashMap<>();
for (Map.Entry<String, Object> map : list) {
sortedMap.put(map.getKey(), map.getValue());
}
为每个值创建一个条目列表,其中对值进行排序需要Java 8或更高版本
Map<Double,List<Entry<String,Double>>> sorted =
map.entrySet().stream().collect( Collectors.groupingBy( Entry::getValue, TreeMap::new,
Collectors.mapping( Function.identity(), Collectors.toList() ) ) );
使用映射{[A=99.5],[B=67.4],[C=67.3],[D=67.3]}得到{67.3=[D=67.3],67.4=[B=67.4,C=67.4],99.5=[A=99.5]}
…以及如何逐个访问每个条目:
sorted.entrySet().forEach( e -> e.getValue().forEach( l -> System.out.println( l ) ) );
D=67.3 B=67.4 C=67.4 A=99.5
使用Guava库:
public static <K,V extends Comparable<V>>SortedMap<K,V> sortByValue(Map<K,V> original){
var comparator = Ordering.natural()
.reverse() // highest first
.nullsLast()
.onResultOf(Functions.forMap(original, null))
.compound(Ordering.usingToString());
return ImmutableSortedMap.copyOf(original, comparator);
}