当我需要按值排序哈希映射时,建议似乎是创建HashMap,然后将数据放入按值排序的TreeMap中。按值排序哈希映射
例如:Sort a Map<Key, Value> by values (Java)
我的问题:为什么有必要做到这一点?为什么不创建一个TreeMap(按键排序),然后按值排序呢?
当我需要按值排序哈希映射时,建议似乎是创建HashMap,然后将数据放入按值排序的TreeMap中。按值排序哈希映射
例如:Sort a Map<Key, Value> by values (Java)
我的问题:为什么有必要做到这一点?为什么不创建一个TreeMap(按键排序),然后按值排序呢?
如果你知道你的值是唯一的,你可以使用番石榴的BiMap(双向映射)来存储数据。创建一个HashBiMap
,你会你HashMap
,然后创建一个从它的逆一个新TreeMap
:
new TreeMap<>(biMap.inverse());
该地图然后由值进行排序。请记住,您正在考虑的“键”和“值”将被交换。
如果你的值不是唯一的,你可以创建一个反转的多图。多重映射本质上是从每个键到一个或多个值的映射。通常通过制作从键到列表的映射来实现。你不必这样做,因为谷歌为你做了。只需从您现有的地图创建一个多地图,并要求番石榴为您翻转为TreeMultimap
,您可以猜到,这是一个TreeMap
,每个关键点可以保存多个值。
Multimaps.invertFrom(Multimaps.forMap(myMap), new TreeMultimap<V, K>());
因为您无法手动重新排序TreeMap
的条目。 TreeMap条目是总是按键排序。
我打算抛出Map that could be iterated in the order of values作为“如何做到这一点”的另一个答案,但是......具体来说,一个解决方案不会返回一个映射(通过抛出异常)来查询键值在你的原始地图。
请注意,如果您不屑于阅读OP中引用的问题,您会注意到TreeMaps并非总是按键排序。 Treemaps可以接受一个比较器,它可以在几乎任何东西(包括值)上进行排序。 – gnomed 2012-02-06 22:39:02
我认为将值放入数组中然后对其进行排序可能更容易。 – 2012-02-06 23:05:56
@gnomed:TreeMap总是按键排序,虽然它可能是根据一些古怪的比较器进行排序(这可能很有可能从别处查找值)。事实上,我确实在阅读OP中引用的问题,尽管它提出了一种技术,当你尝试'map.containsKey(keyNotInOriginalMap)'时,坦率地说很容易出现怪异的错误,并且突然间你会遇到非常混乱的异常,并且不知道你为什么得到它们。 – 2012-02-07 00:03:17
我有这个这是工作的罚款非常小的代码:
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());
唉,我的价值观可能并不是独一无二的,但我会为未来记住这一点。 – 2012-02-06 23:00:48
更新了有关如何使用非唯一值执行此操作的信息。 – 2012-02-07 00:31:46
正是我需要的! – 2012-02-07 11:02:00