【问题标题】:Java maps, going from values to keysJava 映射,从值到键
【发布时间】:2011-04-14 22:21:11
【问题描述】:

有什么方法可以获取与地图中已知值关联的键?通常你知道键并且你想得到值,但我想做相反的事情,从值到键。是否可以?

【问题讨论】:

  • 使值成为键。是的,这就是 Captian Obvious 的说法,但它确实是除了在地图上进行线性搜索之外的唯一方法 - 正如 Larry Wall 指出的那样,这就像试图用装载的 Uzi 将某人击毙。

标签: java maps


【解决方案1】:

是的,您必须遍历映射中的值,然后将每个键存储在一个列表中:

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 关系,这意味着多个键不能映射到同一个值。

【讨论】:

  • 双向地图应该可以工作。如果您不想使用额外的库,只需执行 2 个将值键反转的映射,这就是双向映射的实现方式。
  • 您所描述的双向地图仅适用于数学身份。如果您有两个值指向同一个对象,那么“反向”方向必须有两个键,因此不是数学映射。也许这是一个很好的点,但如果您的数据集具有重复的值,它会产生很大的不同。
  • @Edwin 是正确的,并在网页上的描述中指出:“此映射强制限制键和值之间存在 1:1 关系,这意味着多个键不能映射到同一个价值。”这也是我将两者都作为潜在解决方案提供的原因。我也会在答案中加入警告。
【解决方案2】:

好吧,我不是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();

【讨论】:

    【解决方案3】:

    无需迭代所有键以查找值,您可以使用Apache Commons BidiMap

    【讨论】:

      【解决方案4】:

      映射是一个数学条目,并不意味着反向映射是可能的。也就是说,如果每个映射值都是唯一的,您可能能够创建“反向”映射。当然,您必须将所有数据操作封装在适当更新这两个地图的方法中。

      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) 上循环会更慢,但占用的内存更少。

      【讨论】:

        【解决方案5】:

        这里他们已经谈到了双向地图。如今,Guava (https://github.com/google/guava) 提供了一个不错的 BiMap,您可以将其用于此目的:

        https://github.com/google/guava/wiki/NewCollectionTypesExplained#bimap

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2013-05-04
          • 1970-01-01
          • 2010-12-13
          • 2021-01-07
          • 2018-01-21
          • 1970-01-01
          • 1970-01-01
          • 2013-03-12
          相关资源
          最近更新 更多