【问题标题】:How to create a 2 way map in java如何在java中创建2路地图
【发布时间】:2011-03-26 16:51:15
【问题描述】:

我需要一个数据结构来以 1:1 的关系存储 string-int 值对,并且能够从任何一种方式查找它们的对应对象。

我编写了一个带有 Hashtable 和 String 数组的类,并将数据存储了 2 次,并使用内置函数进行查找。

我的问题是有没有更好的方法来实现这一点?更好的意思是高效且不存储数据 2 次,最好也不编写大量代码:P。

【问题讨论】:

标签: java data-structures


【解决方案1】:

看来您可能正在寻找 bimap。

Google Collections(现在是Guava 的一部分)包含一个带有一些实现的BiMap 接口。

来自BiMap 文档:

双映射(或“双向映射”)是 保留唯一性的地图 它的价值以及它的 键。此约束启用 bimap 支持“逆视图”,即 另一个包含相同的bimap 条目作为此 bimap,但带有 反转键和值。

BiMap.inverse 方法似乎返回了一个Map,其中值作为键,键作为值,因此Map 可用于在值上调用get 并检索键。

另外inverse返回的Map是底层数据的视图,所以它不需要对原始数据进行额外的复制。

来自BiMap.inverse 方法文档:

返回 this 的逆视图 bimap,它映射了这个 bimap 的每一个 值到其关联的键。他们俩 双图由相同的数据支持; 任何更改都会出现在 其他。

【讨论】:

【解决方案2】:

你可以像这样做一个简单的实现。请注意,在此实现中不会复制数据。只有参考文献!我添加了 add 和 get 的实现。 remove 和其他需要的方法留作练习:)

public class TwoWayHashmap<K extends Object, V extends Object> {

  private Map<K,V> forward = new Hashtable<K, V>();
  private Map<V,K> backward = new Hashtable<V, K>();

  public synchronized void add(K key, V value) {
    forward.put(key, value);
    backward.put(value, key);
  }

  public synchronized V getForward(K key) {
    return forward.get(key);
  }

  public synchronized K getBackward(V key) {
    return backward.get(key);
  }
}

当然,即使是“价值观”,它的应用程序责任也是独一无二的。示例用法:

TwoWayHashmap twmap = new TwoWayHashmap<String, String>();
twmap.add("aaa", "bbb");
twmap.add("xxx", "yyy");
System.out.println(twmap.getForward("xxx"));
System.out.println(twmap.getBackward("bbb"));

【讨论】:

  • 在没有 Guava 的 BiMap 的情况下将是一种有趣的方法。但是,我建议您让此类实现 Map 接口。
  • 如果你需要有 Map 接口的类,你可以用 Map inverse() 替换 getBackward 方法,返回逆映射。
【解决方案3】:

Apache Commons 还包括 BidiMap(双向地图)。

定义一个允许键和值之间双向查找的映射。

这个扩展的 Map 表示一个键可以查找一个值的映射 并且一个值可以同样容易地查找一个键。该接口扩展 地图等可以在任何需要地图的地方使用。界面 提供反向地图视图,实现对两个方向的完全访问 的 BidiMap。

【讨论】:

    【解决方案4】:

    Google Guava 有一个 BiMap 可以满足您的需求。

    【讨论】:

    【解决方案5】:

    使用Guava

        HashBiMap<String, String> map = HashBiMap.create();
    
        map.put("name", "Sohail");
        map.put("country", "Pakistan");
    
        Log.d("tag", "name is " + map.get("name"));
    
    
        BiMap<String, String>invmap= map.inverse();
    
        Log.d("tag", "Pakistan is a " + invmap.get("Pakistan"));
    

    阅读完整教程here.

    【讨论】:

      【解决方案6】:

      绝对不用写大量代码 → 在 lambda 中
      从你的Map&lt;String,Integer&gt; map你得到倒置的地图

      Map<Integer,String> inverted = map.keySet().stream().collect(Collectors.toMap( s -> map.get( s ), s -> s ) );
      

      【讨论】:

        【解决方案7】:

        创建一个将 Object 映射到 Object 的 hashmap - 然后您可以使用相同的映射来存储 String -> Integer 和 Integer -> String。

        当您添加一个字符串/整数对时,只需将其两种方式都添加到同一个映射中。

        【讨论】:

        • 这根本不是一个非常明智的实现。您将所有泛型类型安全抛到了窗外,并通过双重添加条目来增加在映射上执行的所有操作的复杂性。没有封装您实现双向映射的机制。
        • @Tom - 我匆忙写下了答案,并假设实现者足够明智地将哈希图包装在一个控制对它的访问并强制转换为所需类型的类中。以后我会尽量明确这一点。
        • 您可能遇到的另一个问题是存储 A->B 和 B->C,这对于问题应该没问题,但对于您的答案则不行。
        猜你喜欢
        • 2023-03-24
        • 2011-01-30
        • 2013-01-22
        • 2022-06-22
        • 1970-01-01
        • 2021-07-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多