Java 中的双向多值映射

2022-09-01 17:40:20

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


答案 1

所以你需要支持多对多的关系吗?最接近的是GuavaMultimap,就像@Mechkov写的一样 - 但更具体地说是与Multimaps.invertFrom的组合。“BiMultimap”尚未实现,但是在Google Guava库中请求此功能时存在问题Multimap

此时,您有几种选择:

  1. 如果你的“BiMultimap”将不可变常量 - 使用和/ /(这三者中的每一个都有不同的集合存储值)。一些代码(示例取自我开发的应用程序,使用s和):Multimaps.invertFromImmutableMultimapImmutableListMultimapImmutableSetMultimapEnumSets.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 可修改,则很难同时维护 K->V 和 V->K 变体,除非您每次想要反转副本时都只进行修改并调用(并使该副本不可修改,以确保您不会意外修改不会更新的内容)。这不是最佳的,但在这种情况下应该这样做。kToVMultimapinvertFromvToKMultimapkToVMultimap

  3. (可能不是你的情况,作为奖励提到):BiMap接口和实现类具有在之后从和自身提供视图的方法。如果我之前提到的这个问题已经完成,它可能会有类似的东西。.inverse()BiMap<V, K>BiMap<K, V>biMap.inverse().inverse()

  4. (编辑2016年10月)您还可以使用新的图形API,它将出现在Guava 20中:

    总体而言,common.graph 支持以下种类的图形:

    • 有向图
    • 无向图
    • 具有关联值(权重、标签等)的节点和/或边
    • 允许/不允许自循环的图形
    • 允许/不允许平行边的图(具有平行边的图有时称为多图)
    • 节点/边按插入顺序、排序或无序排列的图形

答案 2

有两个映射,键>值,值>键有什么问题?


推荐