【问题标题】:How to implement n:m relation in Java?如何在 Java 中实现 n:m 关系?
【发布时间】:2011-04-25 00:11:22
【问题描述】:

我需要在 Java 中实现一个 n:m 关系。 用例是一个目录。

  • 一个产品可以属于多个类别
  • 一个类别可以包含多个产品

我目前的解决方案是拥有一个包含两个哈希图的映射类。

  • 第一个 hashmap 的键是产品 ID,值是类别 ID 列表
  • 第二个 hashmap 的键是类别 ID,值是产品 ID 列表

这完全是多余的,我需要一个设置类来始终注意数据在两个哈希图中的存储/删除。

但这是我发现在 O(1) 中实现以下性能的唯一方法:

  • 哪些产品属于某个类别?
  • 产品属于哪些类别?

我想在各个方面都避免全阵列扫描或类似的事情。

但是必须有另一个更优雅的解决方案,我不需要对数据进行两次索引。

请点亮我。我只有纯 Java,没有数据库或 SQLite 或可用的东西。如果可能的话,我也不想实现 btree 结构。

【问题讨论】:

    标签: java data-structures indexing hashtable hashmap


    【解决方案1】:

    如果您能够使用不可变的数据结构,Guava 的ImmutableMultimap 提供了一个inverse() 方法,使您能够按值获取键的集合。

    【讨论】:

      【解决方案2】:

      如果您通过成员集合将类别与产品相关联,反之亦然,那么您可以完成同样的事情:

      public class Product {
           private Set<Category> categories = new HashSet<Category>();
           //implement hashCode and equals, potentially by id for extra performance
      }
      
      public class Category {
           private Set<Product> contents = new HashSet<Product>();
           //implement hashCode and equals, potentially by id for extra performance
      }
      

      唯一困难的部分是填充这样的结构,其中可能需要一些中间映射。

      但是使用辅助哈希图/树进行索引的方法也不错。毕竟,例如放在数据库上的大多数索引都是辅助数据结构:它们与行表共存;这些行不一定按照索引本身的结构进行组织。

      使用这样的外部结构使您能够将优化和数据彼此分开;这不是一件坏事。特别是如果明天您想为给定供应商的产品添加 O(1) 查找,例如

      编辑: 顺便说一句,看起来你想要的是一个 Multimap 的实现,优化后也可以在 O(1) 中进行反向查找。我不认为 Guava 可以做到这一点,但是您可以实现 Multimap 接口,因此至少您不必单独维护 HashMaps。 实际上它更像是一个 BiMap 也是一个 Multimap鉴于他们的定义,这是矛盾的。我同意 MStodd 的观点,您可能想要滚动自己的抽象层来封装这两个映射。

      【讨论】:

        【解决方案3】:

        我会选择您的第一个解决方案。围绕两个哈希图有一个抽象层。如果您担心并发性,请为 CRUD 实施适当的锁定。

        【讨论】:

          【解决方案4】:

          您的解决方案非常好。请记住,将对象放入 HashMap 并不会复制该对象,它只是存储对它的引用,因此时间和内存成本非常小。

          【讨论】:

          • 谢谢我实际上会继续我的实现,但会接受另一个答案,因为它更适合更“优雅”的解决方案的问题,无论优雅是什么......
          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 2017-08-28
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2015-05-06
          相关资源
          最近更新 更多