【发布时间】:2012-11-11 00:53:37
【问题描述】:
我需要像 TreeMap 这样的排序地图,但按值排序。我的地图会很大,所以我不能在需要的时候对地图进行排序。有什么好的解决方案来解决这个问题吗?也许存在满足这个的外部罐子?
【问题讨论】:
-
最简单的解决方案是同时维护您的
TreeMap和TreeSet的值。
我需要像 TreeMap 这样的排序地图,但按值排序。我的地图会很大,所以我不能在需要的时候对地图进行排序。有什么好的解决方案来解决这个问题吗?也许存在满足这个的外部罐子?
【问题讨论】:
TreeMap 和 TreeSet 的值。
有多种方法可以满足您的要求。正如您随后澄清的那样,您当前的TreeMap 中可能有重复的对象,也许您可以将您的TreeMap 替换为第三方multimap(Guava,Apache Commons Collections),然后交换您的键和值周围 - 即将TreeMap<Key, Value> 替换为Multimap<Value, Key>。根据您的具体情况,我相信这很有可能对您有用。
【讨论】:
如果您使用TreeMap 来维护您的值的索引,即您主要使用它来快速找到给定键的匹配值,那么您可以做的另一件事是保留 2 个数据结构:
TreeMap
PriorityQueue(或其他排序列表)按排序顺序迭代您的值然后,当您有任何更改时,只需在两个列表中添加和删除值。为此,您将不需要保留两个值的副本。您可以简单地将您现在拥有的一份副本添加到两个列表中,因为这些列表仅适用于对您的值的引用。
【讨论】:
实际上并不存在任何可以有效执行此操作的数据结构:您必须维护一个数据结构,以便通过键查找更高效,而对值进行排序则更加困难保持这种结构。
如果您在创建地图后不修改地图,那么您可以执行以下操作:
List<Map.Entry<Key, Value>> list = new ArrayList<Map.Entry<Key, Value>>(
map.entrySet());
Collections.sort(list, new Comparator<Map.Entry<Key, Value>>() {
public int compare(Map.Entry<Key, Value> e1, Map.Entry<Key, Value> e2) {
return e1.getValue().compareTo(e2.getValue());
}
});
Map<Key, Value> sortedByValues = new LinkedHashMap<Key, Value>();
for (Map.Entry<Key, Value> entry : list) {
sortedByValues.put(entry.getKey(), entry.getValue());
}
生成的 LinkedHashMap 将按排序值顺序进行迭代。
【讨论】:
如果您的数据是唯一的,您可以将它们保存在 Set 中,它可以按升序迭代(假设您实现了 Comparable)。
然后,您可以单独持有您的Map,而无需花费太多额外费用,而不仅仅是持有原来的Map。
【讨论】: