我对Java比较陌生,经常发现需要对值进行Map<Key,Value>排序。
由于这些值不是唯一的,我发现自己将keySet转换为一个数组,并使用自定义比较器通过数组排序对该数组进行排序,该比较器根据与该键关联的值进行排序。
有没有更简单的方法?
我对Java比较陌生,经常发现需要对值进行Map<Key,Value>排序。
由于这些值不是唯一的,我发现自己将keySet转换为一个数组,并使用自定义比较器通过数组排序对该数组进行排序,该比较器根据与该键关联的值进行排序。
有没有更简单的方法?
当前回答
重要说明:
此代码可以以多种方式中断。如果您打算使用提供的代码,请务必阅读注释以了解其含义。例如,值不能再通过其键检索。(get始终返回null。)
这似乎比前面所有的都容易得多。按如下方式使用TreeMap:
public class Testing {
public static void main(String[] args) {
HashMap<String, Double> map = new HashMap<String, Double>();
ValueComparator bvc = new ValueComparator(map);
TreeMap<String, Double> sorted_map = new TreeMap<String, Double>(bvc);
map.put("A", 99.5);
map.put("B", 67.4);
map.put("C", 67.4);
map.put("D", 67.3);
System.out.println("unsorted map: " + map);
sorted_map.putAll(map);
System.out.println("results: " + sorted_map);
}
}
class ValueComparator implements Comparator<String> {
Map<String, Double> base;
public ValueComparator(Map<String, Double> base) {
this.base = base;
}
// Note: this comparator imposes orderings that are inconsistent with
// equals.
public int compare(String a, String b) {
if (base.get(a) >= base.get(b)) {
return -1;
} else {
return 1;
} // returning 0 would merge keys
}
}
输出:
unsorted map: {D=67.3, A=99.5, B=67.4, C=67.4}
results: {D=67.3, B=67.4, C=67.4, A=99.5}
其他回答
在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
我可以给你举个例子,但这肯定是你需要的。
map = {10 = 3, 11 = 1,12 = 2}
假设你想要前2个最常用的键,即(10,12)因此,最简单的方法是使用PriorityQueue根据映射的值进行排序。
PriorityQueue<Integer> pq = new PriorityQueue<>((a, b) -> (map.get(a) - map.get(b));
for(int key: map.keySets()) {
pq.add(key);
if(pq.size() > 2) {
pq.poll();
}
}
// Now pq has the top 2 most frequent key based on value. It sorts the value.
我认为最好的方法是使用特殊的数据结构。您可以考虑TreeMap,但在一般情况下,值可能不是唯一的。因此,您的选择是PriorityQueue:
public static <K, V> Iterator<Map.Entry<K, V>> sortByValue(
Map<K, V> map,
Comparator<V> valueComparator) {
Queue<Map.Entry<K, V>> queue = new PriorityQueue<>((one, two) ->
valueComparator.compare(one.getValue(), two.getValue()));
queue.addAll(map.entrySet());
return queue.iterator();
}
如果没有大于地图大小的值,可以使用数组,这应该是最快的方法:
public List<String> getList(Map<String, Integer> myMap) {
String[] copyArray = new String[myMap.size()];
for (Entry<String, Integer> entry : myMap.entrySet()) {
copyArray[entry.getValue()] = entry.getKey();
}
return Arrays.asList(copyArray);
}