Java中的双向多值映射

时间:2011-11-09 14:01:29

标签: java multimap

我正在寻找一种存储键值对的方法。我需要查找是双向的,但同时我需要为同一个密钥存储多个值。换句话说,比如BidiMap,但是对于每个键,可以有多个值。例如,它需要能够保持像对象:“s1” - > 1,“s2” - > 1,“s3” - > 2,我需要能够获取映射到每个的值key,并为每个值获取与之关联的所有键。

6 个答案:

答案 0 :(得分:20)

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

此时你几乎没有选择:

  1. 如果你的“BiMultimap”是不可变的常量 - 使用Multimaps.invertFromImmutableMultimap / ImmutableListMultimap / ImmutableSetMultimap(每个人都有不同的收藏存储值)。一些代码(从我开发的应用程序中获取的示例,使用EnumSets.immutableEnumSet):

    public class RolesAndServicesMapping {
        private static final ImmutableMultimap<Service, Authority> SERVICES_TO_ROLES_MAPPING = 
             ImmutableMultimap.<Service, Authority>builder()
                .put(Service.SFP1, Authority.ROLE_PREMIUM)
                .put(Service.SFP, Authority.ROLE_PREMIUM)
                .put(Service.SFE, Authority.ROLE_EXTRA)
                .put(Service.SF, Authority.ROLE_STANDARD)
                .put(Service.SK, Authority.ROLE_STANDARD)
                .put(Service.SFP1, Authority.ROLE_ADMIN)
                .put(Service.ADMIN, Authority.ROLE_ADMIN)
                .put(Service.NONE, Authority.ROLE_DENY)
                .build();
    
        // Whole magic is here:
        private static final ImmutableMultimap<Authority, Service> ROLES_TO_SERVICES_MAPPING =
                SERVICES_TO_ROLES_MAPPING.inverse();
        // before guava-11.0 it was: ImmutableMultimap.copyOf(Multimaps.invertFrom(SERVICES_TO_ROLES_MAPPING, HashMultimap.<Authority, Service>create()));
    
        public static ImmutableSet<Authority> getRoles(final Service service) {
            return Sets.immutableEnumSet(SERVICES_TO_ROLES_MAPPING.get(service));
        }
    
        public static ImmutableSet<Service> getServices(final Authority role) {
            return Sets.immutableEnumSet(ROLES_TO_SERVICES_MAPPING.get(role));
        }
    }
    
  2. 如果您真的希望Multimap可以修改,除非您只修改kToVMultimap并调用{{{}},否则很难同时维护K-> V和V-> K变体1}}每次你想要它的反转副本(并使该副本不可修改,以确保你不小心不修改invertFrom什么不会更新vToKMultimap)。这不是最佳选择,但在这种情况下应该这样做。

  3. (可能不是你的情况,作为奖励提到):BiMap接口和实现类有kToVMultimap方法,它在.inverse()之后提供BiMap<V, K>视图BiMap<K, V>。如果我之前提到的this issue完成了,它可能会有类似的东西。

  4. (2016年10月编辑)您还可以使用new graph API中出现的Guava 20

      

    作为一个整体,common.graph支持以下类型的图表:

         
        
    • 有向图
    •   
    • 无向图
    •   
    • 具有关联值(权重,标签等)的节点和/或边缘
    •   
    • 允许/不允许自我循环的图表
    •   
    • 允许/不允许平行边的图(具有平行边的图有时称为多图)
    •   
    • 其节点/边缘是插入排序,排序或无序的图表
    •   

答案 1 :(得分:1)

有两张地图,键 - >值,值 - >键有什么问题?

答案 2 :(得分:1)

我希望使用MultivaluedMap解决问题。 请在下面的链接中找到oracle的文档。

http://docs.oracle.com/javaee/6/api/javax/ws/rs/core/MultivaluedMap.html

答案 3 :(得分:1)

使用Google Guava,我们可以编写如下的原始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方法

答案 4 :(得分:-2)

希望我帮到你了

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

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

答案 5 :(得分:-3)

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

Map<Key Collection<Values>> 

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