【问题标题】:Data-structure of Pairs where each value (in pair) Maps to other value?每个值(成对)映射到其他值的对的数据结构?
【发布时间】:2012-03-27 01:25:35
【问题描述】:

我又带着类似的问题回来了。是否有可以返回其特定合作伙伴的 DataType?例如:

ExampleType<String,String> test = new ExampleType<String,String>();
test.put("hello","hi");

如果我输入 test.get("hi"),它会返回 "hello",如果我输入 test.get("hello"),它会返回 "hi"。

我对此的唯一猜测可能是一个二维数组,但我不确定我将如何实现它。截至目前,我能理解的唯一方法是创建两个不同的哈希映射并交换每个哈希映射中的键。 (显然这不是很有效/有效)。

感谢大家的帮助!

【问题讨论】:

  • 有时“显而易见”的东西在旁观者的眼中。一对地图对我来说听起来不错。

标签: java data-structures map


【解决方案1】:

您可以为此使用Guava's BiMap。它也支持反向查找:

双映射(或“双向映射”)是一种映射,它保留其值的唯一性以及其键的唯一性。此约束使 bimap 能够支持“反向视图”,这是另一个 bimap,包含与此 bimap 相同的条目,但具有相反的键和值。

如果您已经依赖于 commons-collections,那么您也可以使用BidiMap

【讨论】:

  • +1 图书馆建议。但是请注意,额外的约束可能使其不适用于所有类似的任务。 (这是一个 1-1 映射,而不是带有反向查找映射的 1-N。)
【解决方案2】:

没有内置任何东西,因此您要么使用 Pangea 提到的 Guava 的 BiMap 之类的第 3 方包,或者,如果您想推出自己的包,如果您需要两种不同的数据类型,那么 2-maps 的想法也不错,如果您的键和值是相同的类型,您可以使用带有双条目的单个映射:

public class BiMap<T>{

    private Map<T,T> theMap = new HashMap<T,T>();

    public void put( T key, T value ){ put( key, value, false ); }
    public void forcePut( T key, T value ){ put( key, value, true ); }

    private void put( T key, T value, boolean force ){
        if( force || !theMap.containsKey(value) ){
            theMap.remove( theMap.remove( key ) );
            theMap.put( key, value );
            theMap.put( value, key );
        }else if( !theMap.get( value ).equals( key ) ){
            // If you allow null values&keys this will get more complicated.

            throw new IllegalArgumentException();
            // can make this more informative.
        }
        // else the pair is already in, there's nothing to do.
    }

    public T get( T key ){ return theMap.get( key ); }

    public T remove( T key ){
        T value = theMap.remove( key );
        if( value != null ) theMap.remove( value );
        return value;
    }
}

请注意,因为一切都是对象,所以就效率/空间而言并没有太多浪费:您存储两次的唯一内容是对象地址。您的 2-map 想法也是如此。

此外,为了合规性,添加必要的方法来实现Map&lt;T,T&gt; 接口也不会太难。

【讨论】:

  • 我可能会扩展HashMap&lt;T,T&gt;
  • 如果你 put 重叠键,那会有“令人惊讶”的行为。 test.put("a", "b"); test.put("a", "c"); test.get(test.get("b")) 不返回 "b"
  • 好收获。我会纠正它。我现在拥有的put 是一个肮脏的forcePut
  • 当你对奇怪的案例进行所有测试时,我想它并不像我最初想象的那么优雅。
【解决方案3】:

假设您不打算区分您要查询的对的哪一部分(也就是说,您想查看

test.get("hi") => "hello"
test.get("hello") => "hi"

为什么不把两个键都插入同一张地图?

test.put("hello","hi");
test.put("hi","hello");

【讨论】:

    【解决方案4】:

    两个 ArrayList 可能是最简单的。只要确保将这些对存储在同一个索引中,它应该可以正常工作。代码看起来像:

    ArrayList<String> list1 = new ArrayList<String>();
    ArrayList<String> list2 = new ArrayList<String>();
    list1.add("hi");
    list2.add("hello");
    get("hi");
    

    还有你的get方法:

    get(String s){
        return list2.get( list1.indexOf(s) );
    }
    

    不知道这是否是最好的解决方案,但它是一个解决方案。

    【讨论】:

    • 这是一个非常弱的解决方案。他已经在使用地图了,为什么要放弃继续使用地图呢?
    猜你喜欢
    • 2020-03-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-04-07
    • 2015-12-10
    • 1970-01-01
    • 2020-04-20
    • 1970-01-01
    相关资源
    最近更新 更多