【发布时间】:2011-04-14 22:21:11
【问题描述】:
有什么方法可以获取与地图中已知值关联的键?通常你知道键并且你想得到值,但我想做相反的事情,从值到键。是否可以?
【问题讨论】:
-
使值成为键。是的,这就是 Captian Obvious 的说法,但它确实是除了在地图上进行线性搜索之外的唯一方法 - 正如 Larry Wall 指出的那样,这就像试图用装载的 Uzi 将某人击毙。
有什么方法可以获取与地图中已知值关联的键?通常你知道键并且你想得到值,但我想做相反的事情,从值到键。是否可以?
【问题讨论】:
是的,您必须遍历映射中的值,然后将每个键存储在一个列表中:
for (Map.Entry<K,V> entry : map.entrySet()) {
V value = entry.getValue();
if (value.equals(someTargetValue) {
// add key (entry.getKey()) to list
}
}
或者您可以使用bidirectional map,但请注意:
此映射强制限制键和值之间存在 1:1 关系,这意味着多个键不能映射到同一个值。
【讨论】:
好吧,我不是Google Project LambdaJ 的专家,但它确实提供了一些很酷的选择。
假设您有一张包含一个月中所有日期的地图:
month.put(1,"Monday");
month.put(2,"Tuesday");
month.put(3,"Wednesday");
...
然后我们可以像这样轻松实现您想要的:
Set<Integer> result = with(month).retainValues(is("Friday")).keySet();
甚至是一些更有趣的搜索,例如:
Set<Integer> result = with(month).retainValues(anyOf(is("Monday"),is("Friday"))).keySet();
【讨论】:
无需迭代所有键以查找值,您可以使用Apache Commons BidiMap
【讨论】:
映射是一个数学条目,并不意味着反向映射是可能的。也就是说,如果每个映射值都是唯一的,您可能能够创建“反向”映射。当然,您必须将所有数据操作封装在适当更新这两个地图的方法中。
Map<Key, Value> normal;
Map<Value, Key> reverse;
如果每个映射的值都不是唯一的,那么您需要创建一个值到键列表的反向映射。
Map<Key, Value> normal;
Map<Value, List<Key>> reverse;
最后,如果您不关心快速访问,您可以遍历整个 Map 以查找 Values。由于您需要 Value 和 Key,因此最好遍历 Map.Entry 项。
Value searchingFor = ...;
Map<Key, Value> normal;
List<Key> keys = new ArrayList<Key>();
for (Map.Entry<Key, Value> entry : normal.entrySet()) {
if (entry.getValue().equals(searchingFor)) {
keys.add(entry.getKey());
}
}
您选择使用的技术在很大程度上取决于以速度换取内存占用是否更好。由于对 Value(s) 进行哈希处理,通常拥有一个额外的 Map 会更快,但会消耗额外的内存。在 Map.Entry(s) 上循环会更慢,但占用的内存更少。
【讨论】:
这里他们已经谈到了双向地图。如今,Guava (https://github.com/google/guava) 提供了一个不错的 BiMap,您可以将其用于此目的:
https://github.com/google/guava/wiki/NewCollectionTypesExplained#bimap
【讨论】: