Java 中的双向多值映射
我正在寻找一种存储键值对的方法。我需要查找是双向的,但同时我需要为同一键存储多个值。换句话说,类似于BidiMap的东西,但对于每个键可以有多个值。例如,它需要能够容纳这样的对:“s1”->1,“s2”->1,“s3”->2,我需要能够获得映射到每个键的值,并且对于每个值,获取与其关联的所有键。
我正在寻找一种存储键值对的方法。我需要查找是双向的,但同时我需要为同一键存储多个值。换句话说,类似于BidiMap的东西,但对于每个键可以有多个值。例如,它需要能够容纳这样的对:“s1”->1,“s2”->1,“s3”->2,我需要能够获得映射到每个键的值,并且对于每个值,获取与其关联的所有键。
所以你需要支持多对多的关系吗?最接近的是Guava的Multimap
,就像@Mechkov写的一样 - 但更具体地说是与Multimaps.invertFrom
的组合。“BiMultimap”尚未实现,但是在Google Guava库中请求此功能时存在问题。Multimap
此时,您有几种选择:
如果你的“BiMultimap”将不可变常量 - 使用和/ /(这三者中的每一个都有不同的集合存储值)。一些代码(示例取自我开发的应用程序,使用s和):Multimaps.invertFrom
ImmutableMultimap
ImmutableListMultimap
ImmutableSetMultimap
Enum
Sets.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));
}
}
如果您真的希望 Multimap 可修改,则很难同时维护 K->V 和 V->K 变体,除非您每次想要反转副本时都只进行修改并调用(并使该副本不可修改,以确保您不会意外修改不会更新的内容)。这不是最佳的,但在这种情况下应该这样做。kToVMultimap
invertFrom
vToKMultimap
kToVMultimap
(可能不是你的情况,作为奖励提到):BiMap
接口和实现类具有在之后从和自身提供视图的方法。如果我之前提到的这个问题已经完成,它可能会有类似的东西。.inverse()
BiMap<V, K>
BiMap<K, V>
biMap.inverse().inverse()
(编辑2016年10月)您还可以使用新的图形API,它将出现在Guava 20中:
总体而言,common.graph 支持以下种类的图形:
- 有向图
- 无向图
- 具有关联值(权重、标签等)的节点和/或边
- 允许/不允许自循环的图形
- 允许/不允许平行边的图(具有平行边的图有时称为多图)
- 节点/边按插入顺序、排序或无序排列的图形
有两个映射,键>值,值>键有什么问题?