Java中的双向多值映射 [英] Bidirectional multi-valued map in Java

查看:27
本文介绍了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.

推荐答案

所以您需要多对多关系的支持?最接近的是 GuavaMultimap 喜欢@Mechkov 写道 - 但更具体地说是 MultimapMultimaps.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.

此时您有几个选择:

  1. 如果您的BiMultimap"将成为不可变常量 - 使用 Multimaps.invertFromImmutableMultimap/ImmutableListMultimap/ImmutableSetMultimap(这三个中的每一个都有不同的集合存储值).一些代码(示例取自我开发的应用程序,使用 Enums 和 Sets.immutableEnumSet):

  1. If your "BiMultimap" is going to immutable constant - use Multimaps.invertFrom and ImmutableMultimap / ImmutableListMultimap / ImmutableSetMultimap (each of theese three has different collection storing values). Some code (example taken from app I develop, uses Enums and 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).这不是最佳选择,但在这种情况下应该这样做.

  • 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<来自 BiMapbiMap.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屋!

    查看全文
    登录 关闭
    扫码关注1秒登录
    发送“验证码”获取 | 15天全站免登陆