Java中的双向多值映射 [英] Bidirectional multi-valued map in Java
问题描述
我正在寻找一种存储键值对的方法.我需要双向查找,但同时我需要为同一个键存储多个值.换句话说,类似于 BidiMap,但对于每个键可以有多个值.例如,它需要能够保存像这样的对:s1"->1、s2"->1、s3"->2,并且我需要能够将值映射到每个键,并且对于每个值,获取与其关联的所有键.
I am looking for a way to store key-value pairs. I need the lookup to be bidirectional, but at the same time I need to store multiple values for the same key. In other words, something like a BidiMap, but for every key there can be multiple values. For example, it needs to be able to hold pairs like: "s1"->1, "s2"->1, "s3"->2, and I need to be able to get the value mapped to each key, and for each value, get all the keys associated with it.
推荐答案
所以您需要多对多关系的支持?最接近的是 Guava 的 Multimap
喜欢@Mechkov 写道 - 但更具体地说是 Multimap
与 Multimaps.invertFrom
.BiMultimap"尚未实现,但存在一个问题 在 Google Guava 库中请求此功能.
So you need support for many-to-many relationships? Closest you can get is Guava's Multimap
like @Mechkov wrote - but more specifically Multimap
combination with Multimaps.invertFrom
. "BiMultimap" isn't implemented yet, but there is an issue requesting this feature in Google Guava library.
此时您有几个选择:
如果您的BiMultimap"将成为不可变常量 - 使用
Multimaps.invertFrom
和ImmutableMultimap
/ImmutableListMultimap
/ImmutableSetMultimap
(这三个中的每一个都有不同的集合存储值).一些代码(示例取自我开发的应用程序,使用Enum
s 和Sets.immutableEnumSet
):
If your "BiMultimap" is going to immutable constant - use
Multimaps.invertFrom
andImmutableMultimap
/ImmutableListMultimap
/ImmutableSetMultimap
(each of theese three has different collection storing values). Some code (example taken from app I develop, usesEnum
s andSets.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代码>).这不是最佳选择,但在这种情况下应该这样做.
If you really want your Multimap to be modifiable, it will be hard to maintain both K->V and V->K variants unless you will be modifying only kToVMultimap
and call invertFrom
each time you want to have its inverted copy (and making that copy unmodifiable to make sure that you accidentally don't modify vToKMultimap
what wouldn't update kToVMultimap
). This is not optimal but should do in this case.
(可能不是你的情况,作为奖励提到):BiMap
接口和实现类有 .inverse()
方法,它给出 BiMap<来自
视图.如果我之前提到的这个问题完成了,它会可能有类似的东西.BiMap
和 biMap.inverse().inverse()
之后的 V, K>
(Not your case probably, mentioned as bonus): BiMap
interface and implementing classes has .inverse()
method which gives BiMap<V, K>
view from BiMap<K, V>
and itself after biMap.inverse().inverse()
. If this issue I mentioned before is done, it will probably have something similar.
(2016 年 10 月编辑)您还可以使用 new图 API 将出现在 番石榴 20:
(EDIT October 2016) You can also use new graph API which will be present in Guava 20:
总的来说,common.graph 支持以下种类的图:
As a whole, common.graph supports graphs of the following varieties:
- 有向图
- 无向图
- 具有关联值(权重、标签等)的节点和/或边
- 允许/不允许自循环的图表
- 允许/不允许平行边的图(具有平行边的图有时称为多重图)
- 节点/边为插入顺序、排序或无序的图
这篇关于Java中的双向多值映射的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!