【问题标题】:Use a Java hash map even when there is no "mapping"?即使没有“映射”,也要使用 Java 哈希映射?
【发布时间】:2010-12-30 23:00:56
【问题描述】:

我想存储一些对象,然后能够尽可能高效地检索它们。我也会在某些条件下删除其中的一些。看来哈希映射是正确的选择。

但是,据我所知,哈希映射总是将一个值与另一个值相关联?例如,“john”和“555-5555”,他的电话号码。

现在,我的情况。假设我有一群人,每个人都与其他人有联系。所以,我需要每个人都存储其联系人。

我正在做的是让每个人都有一个哈希图,然后我会添加到哈希 otherPerson, otherPerson。基本上,关键是价值。我做错了吗?

编辑我认为 HashSet 不会解决我的问题,因为我必须检索值来更新它并且没有 get 方法。删除返回一个布尔值,所以我什至不能删除它来重新放回去,这可能是个坏主意。

【问题讨论】:

  • 听起来你想要的是一个集合而不是地图。而且我不会太沉迷于散列。您使用什么语言?
  • 您将使用什么标准来检索对象?该标准听起来像是使用的最佳哈希......

标签: java data-structures hashtable hashmap hash


【解决方案1】:

好吧,我认为您要在这里寻找的数据结构将是一个 HashSet(或其他类型的集合)(如果您的框架/库提供它)。一组只是说“我有以下项目”而不是“我有以下项目映射到以下值”。这就是您在此处建模的内容。

至于 HashSet 与其他实现(如果存在):这完全取决于您在做什么。如果您需要快速查找,我。 e. “这个元素在集合中吗?”问题,那么散列是一件好事。其他底层数据结构可能更适合其他集合操作,例如联合、交集等。

【讨论】:

    【解决方案2】:

    哈希表/映射只要求您有一种方法来获取您以后有兴趣查找的值;这就是钥匙的用途。

    但是,在您的具体情况下,听起来您正在寻找一种方法来存储人与人之间的关系,而您要跟踪的是 A 是否与 B 有关系。更好的表示因为那种东西是 adjacency list

    【讨论】:

      【解决方案3】:

      我是否遗漏了什么,或者您不需要ArrayList<Person>

      【讨论】:

      • 数组列表使用元素索引来查找。索引对我来说并不重要,与元素无关。我可以使用 indexOf(Object) 然后将结果与 get 一起使用,但这不是效率很低吗?它不是必须通过两次数据结构吗?这似乎很糟糕。我会经常这样做,所以我认为使用哈希映射会更好。
      • 它可能是,然后再一次,你必须对其进行分析才能真正确定。此时,您正在存储联系人列表,因此 ArrayList 似乎是最直接的。当你测量它时,我会担心瓶颈。但你可能有过经验告诉你这将是一个瓶颈,我不知道。
      【解决方案4】:

      如果您只需要检查 A 是否是 B 的联系人之一,那么 Set 就是选择。为此目的,它有 contains()。

      否则,最合适的可能是 Map,因为您需要高效的检索操作。你说目前你使用相同的对象作为键和值,但我不确定你是如何获得键的。假设您想从 B 的联系人中获取联系人 A,并且您使用诸如“B.contacts.get(A)”之类的内容,您从哪里获得 A?如果你已经有了A,那又要从地图上得到它又是什么? (也许同一个人有多个实例?)

      除非同一个人有多个实例,否则我会为每个 Person 定义一个 ID,如唯一属性,并将其用作联系人映射的键。另外,你是否为 person 类定义了 equal()/hashCode() ? Map/Set 使用 hashCode() 和 equal() 来查找匹配项。根据您的使用情况,您可能需要考虑重写它们以提高效率。

      【讨论】:

        【解决方案5】:

        我只会将联系人存储在List<Person> 中。例如

        public class Person {
            private List<Person> contacts;
        }
        

        关于编辑个人联系人,这真的不是父母Person的责任。它应该在最高添加/删除联系人。您可以通过contacts.add(otherPerson)contacts.remove(otherPerson) 完美地做到这一点。

        当您想编辑可能是其中一个联系人的个人Person 时,只需独立处理它,例如personDAO.find(personId) 然后相应地更新它。实际上,编辑自己的详细信息也是Person 自己的责任。借助良好的 ORM,这些更改将反映在其他 Persons 的联系人列表中。

        【讨论】:

          【解决方案6】:

          我认为 HashSet 不能解决我的问题,因为我必须检索值来更新它并且没有 get 方法。

          这是一个令人费解的说法。为什么要使用get 方法检索值来更新它?当然,如果您知道需要从集合/映射中检索哪个对象,则无需检索它。

          例如:

          HashSet<Person> relations = ...
          Person p = ...
          if (relations.remove(p)) {
              // we removed an object such that p.equals(obj) is true.
          }
          

          现在,如果您担心被删除的对象与p 相同,但不完全相同,在我看来,您的设计有问题。要么:

          • 您不应该创建多个相等的Person 实例,或者
          • 您不应该关心Person 实例不相同,或者
          • 你不应该覆盖equals(Object)

          简而言之,问题在于您没有正确管理对象身份。

          【讨论】:

            【解决方案7】:

            如果您需要遍历人员,或要求他们进行排序,请考虑使用 TreeMap 或 TreeSet 而不是散列。

            【讨论】:

              猜你喜欢
              • 2020-01-08
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 2018-10-13
              • 1970-01-01
              • 2016-04-24
              • 2014-09-16
              相关资源
              最近更新 更多