2011-11-09 79 views
19

我正在寻找一种方法来存储键值对。我需要查找是双向的,但同时我需要为同一个密钥存储多个值。换句话说,像BidiMap这样的东西,但是对于每个键都可以有多个值。例如,它需要能够保存像“s1” - > 1,“s2” - > 1,“s3” - > 2这样的对,并且我需要能够将值映射到每个键,并且对于每个值,获取与其关联的所有密钥。Java中的双向多值映射

+3

您提到每个键需要多个值,但在您的示例中,您没有具有多个值的键,而是具有两个键的值。你应该澄清一点。如果你的例子适合你的问题,你会得到更好的答案;-) – pushy

+0

http://www.jguru.com/faq/view.jsp?EID=1317828在这里你可以找到如何创建multimap – maks

+0

@pushy,同样的问题,如果我反转地图,并保留整数作为键而不是值,我会得到一对多的映射。无论如何,感谢您的更正。 :) –

回答

19

所以你需要支持多对多的关系吗?最近你可以得到GuavaMultimap就像@Mechkov写的 - 但更具体地说Multimap组合Multimaps.invertFrom。 “BiMultimap”尚未实现,但在Google Guava库中请求此功能的an issue

在这一点上,你有几种选择:

  1. 如果你的“BiMultimap”将不可变不变 - 使用Multimaps.invertFromImmutableMultimap/ImmutableListMultimap/ImmutableSetMultimap(每个theese三个具有不同的收集保存的值)。某些代码(例如,从应用程序开发我取,使用Enum S和Sets.immutableEnumSet):

    ​​
  2. 如果你真的想你Multimap之要修改,这将是难以维持两个K-> V与V-> K变体,除非您每次需要修改kToVMultimap并致电invertFrom(并且使该副本不可修改,以确保您不小心不会修改vToKMultimap什么不会更新kToVMultimap)。这不是最佳的,但应该在这种情况下。

  3. (不是你的情况可能是,提到奖金):BiMap接口和实现类具有.inverse()方法,给出了从BiMap<K, V>BiMap<V, K>视图和自身biMap.inverse().inverse()后。如果我之前提到的this issue完成了,它可能会有类似的东西。

  4. (编辑2016年10月)您也可以使用new graph API这将是目前在Guava 20

    作为一个整体,共同的。图形支持的以下品种图:

    • 向图
    • 无向图
    • 节点和/或边缘与相关联的值(权重,标签等)
    • 图表,做/不允许自循环
    • 图表,做/不允许平行的边缘(与平行边缘图有时被称为多重图)
    • 图的节点/边缘插入顺序,分类或无序
-1

希望我把你的右

class A { 
    long id; 
    List<B> bs; 
} 

class B { 
    long id; 
    List<A> as; 
} 
2

出了什么问题有两个地图,键 - >值,值 - >键?

+3

我认为保留相同数据的两个副本会更容易出错。无论如何,在我看过的所有藏品之后,我开始认为这是最好的解决方案。 –

+2

只需为保持同步的地图创建一个包装。 – Stefan

+10

我不喜欢这个答案认可的方法。这有很多可能的错误,包括重新发明轮子,沿途编写自己的错误,线程安全等。 – bacar

-3

谷歌的Guava MultiMap实现是我用于这些目的。

Map<Key Collection<Values>> 

其中Collection可以是一个ArrayList例如。它允许存储在一个集合中的多个值映射到一个键。 希望这有助于!

+0

不是双向的。 – Stefan

1

使用谷歌番石榴,我们可以如下编写原始BiMulitMap。

import java.util.Collection; 

import com.google.common.collect.ArrayListMultimap; 
import com.google.common.collect.Multimap; 

public class BiMultiMap<K,V> { 

    Multimap<K, V> keyToValue = ArrayListMultimap.create(); 
    Multimap<V, K> valueToKey = ArrayListMultimap.create(); 

    public void putForce(K key, V value) { 
     keyToValue.put(key, value); 
     valueToKey.put(value, key); 
    } 

    public void put(K key, V value) { 
     Collection<V> oldValue = keyToValue.get(key); 
     if (oldValue.contains(value) == false) { 
      keyToValue.put(key, value); 
      valueToKey.put(value, key); 
     } 
    } 

    public Collection<V> getValue(K key) { 
     return keyToValue.get(key); 
    } 

    public Collection<K> getKey(V value) { 
     return valueToKey.get(value); 
    } 

    @Override 
    public String toString() { 
     return "BiMultiMap [keyToValue=" + keyToValue + ", valueToKey=" + valueToKey + "]"; 
    } 

} 

希望这将有助于双向多地图的一些基本需求。 请注意K和V需要正确实施hascode和equals方法