【发布时间】:2012-02-06 22:26:29
【问题描述】:
当我需要按值对 HashMap 进行排序时,建议似乎是创建 HashMap,然后将数据放入按值排序的 TreeMap。
例如:Sort a Map<Key, Value> by values (Java)
我的问题:为什么有必要这样做?为什么不创建一个 TreeMap(按键排序),然后按值排序?
【问题讨论】:
当我需要按值对 HashMap 进行排序时,建议似乎是创建 HashMap,然后将数据放入按值排序的 TreeMap。
例如:Sort a Map<Key, Value> by values (Java)
我的问题:为什么有必要这样做?为什么不创建一个 TreeMap(按键排序),然后按值排序?
【问题讨论】:
如果你知道你的值是唯一的,你可以使用 Guava 的BiMap(双向映射)来存储数据。像创建HashMap 一样创建HashBiMap,然后从其逆向创建一个新的TreeMap:
new TreeMap<>(biMap.inverse());
然后该地图将按值排序。请记住,您认为的“键”和“值”将被交换。
如果您的值不是唯一的,您可以创建逆的多重映射。多重映射本质上是从每个键到一个或多个值的映射。它通常通过制作从键到列表的映射来实现。不过,您不必这样做,因为 Google 为您做到了。只需从您现有的地图创建一个多地图,然后让 Guava 为您将其反转为 TreeMultimap,您可以猜到,这是一个 TreeMap,每个键可以保存多个值。
Multimaps.invertFrom(Multimaps.forMap(myMap), new TreeMultimap<V, K>());
【讨论】:
因为您无法手动重新排序 TreeMap 的条目。 TreeMap 条目总是按键排序。
我将扔掉Map that could be iterated in the order of values 作为“如何做”的另一个答案...具体来说,一个解决方案不会返回一个在查询键时阻塞(通过抛出异常)的映射不在您的原始地图中。
【讨论】:
map.containsKey(keyNotInOriginalMap) 时坦率地说很容易出现古怪错误的技术,突然间您会遇到非常令人困惑的异常并且不知道为什么您会得到他们。
List<V> theValues = new ArrayList<V>(map.values()); Collections.sort(theValues);
我有这个运行良好的非常小的代码:
public class SortMapByValues {
public static void main(String[] args) {
Map<Integer, String> myMap = new LinkedHashMap<Integer, String>();
myMap.put(100, "hundread");
myMap.put(500, "fivehundread");
myMap.put(250, "twofifty");
myMap.put(300, "threehundread");
myMap.put(350, "threefifty");
myMap.put(400, "fourhundread");
myMap = sortMapByValues(myMap);
for (Map.Entry<Integer, String> entry : myMap.entrySet()) {
System.out.println(entry.getKey() + " " + entry.getValue());
}
}
public static Map<Integer, String> sortMapByValues(
Map<Integer, String> firstMap) {
Map<String, Integer> SecondyMap = new TreeMap<String, Integer>();
for (Map.Entry<Integer, String> entry : firstMap.entrySet()) {
SecondyMap.put(entry.getValue(), entry.getKey());
}
firstMap.clear();
for (Map.Entry<String, Integer> entry : SecondyMap.entrySet()) {
firstMap.put(entry.getValue(), entry.getKey());
}
return firstMap;
}
}
输出:
500 fivehundread
400 fourhundread
100 hundread
350 threefifty
300 threehundread
250 twofifty
【讨论】:
我使用 Java 8 Stream API 编写了以下单行代码,以按值对任何给定地图进行排序:
List<Map.Entry<String, String>> sortedEntries = map.entrySet().stream()
.sorted((o1, o2) -> o1.getValue().compareTo(o2.getValue())).collect(Collectors.toList());
【讨论】: