【问题标题】:How to improve search in an array of HashMap如何改进 HashMap 数组中的搜索
【发布时间】:2015-02-15 14:41:43
【问题描述】:

在任何 HashMap(或任何基于散列的数据结构)中的搜索都需要单个散列操作,即 O(1)。但是,当我们必须搜索 HashMaps 数组时,单个搜索将需要 O(n) 哈希操作,其中 n 是数组的大小。我想知道,由于数组是连续内存位置的集合,因此可能有一种有效的方法可以将 HashMap 数组中的搜索从 O(n) 减少到 O(1)。或者我们可以设计一些对象,它实际上具有数组的优势,并且需要单个哈希运算进行搜索。有什么建议吗???

考虑这种情况,您正在处理来自不同用户的元素,并且您希望根据用户配置文件(彼此分开)来保留它们。最节省内存的方法是使用 HashMap 数组将它们分开。

【问题讨论】:

  • 为什么首先要有一个 HashMap 数组?
  • 您采用了一种非常奇怪且有问题的数据结构,并询问是否有可能设计出更好的数据结构。是的,它已经完成了。首先停止使用奇怪和可疑的。 :-)
  • 可能有不同的原因。例如,我必须在 HashMap 中维护元素。由于某些原因,当 HashMap 中的元素数量增加时,我创建了另一个 HashMap。我知道会创建多少个 HashMap,所以我创建了一个 HashMap 数组。同时我必须搜索一些元素,这就是为什么我需要 HashMap 数组
  • HashMap 会自动扩展大小。当元素数量增加时,无需创建第二个。
  • 不,最有效的方法是保留n 单独的hashmap 和一个整体hashmap,这样您就可以为想要执行的每种查询类型创建一个map。额外hashmap的开销只在结构中,不会复制任何用户数据。

标签: java arrays algorithm hash


【解决方案1】:

这个问题的答案就在你的问题中。当你使用一个普通的 Array 来存储这些元素时,搜索它时没有办法得到 O(1) 的复杂度。

您说搜索哈希映射的复杂度是 O(1),那么为什么不将这些哈希映射存储在哈希映射中呢?我将把它的实现留给你,哈哈。

【讨论】:

  • 在 HashMap 中存储 HashMap 是行不通的。例如 HashMap,Integer> obj=new HashMap();如果没有遍历所有哈希图的循环,则无法在 obj 中搜索字符串
  • @user3212493 您需要为每个地图配置一个允许您搜索它的键;这就是地图的全部意义所在。你上面给出的例子当然不允许智能搜索顶部地图,因为你给了它一个你事先不知道的键。请参阅我的答案以获得更合理的实施。
【解决方案2】:

Go Go For java.util 包,Go Go for Java 集合

查看基于集合 (Hashset, enumset) 和哈希 (HashMap,linkedhash...,idnetityhash..) 的实现。 they have O(1) for contains()

以下是供参考的统计数据。

【讨论】:

  • 我知道这个包,但在我看来,没有一个可以解决我的问题,因为我正在谈论 HashMap 数组。在 HashMap 数组中搜索是 O(n)。当然,在单个 HashMap 中的搜索是 O(1)。
  • @user3212493 那么没有这样的标准 API 可用,是时候编写自己的算法来实现这一点了。
【解决方案3】:

我已经编辑了您的问题,以包含各种用户帐户的假设场景,每个帐户都有不同的属性。正如另一个答案中提到的,这里的解决方案是地图的地图。发生了两个单独的搜索:

  1. 找到合适的用户
  2. 找到该用户的正确财产

这些搜索中的每一个都可以使用单独的地图完成。

用户地图:

class Application {

    ...

    Map<String, User> userMap = new HashMap<>();

    public User getUser(String userName) {
        return userMap.get(userName);
    }

    ...
}

属性图:

class User {

    ...

    Map<String, Property> propertyMap = new HashMap<>();

    public Property getProperty(String propertyName) {
        return propertyMap .get(propertyName);
    }

    ...
}

现在找到名为Arthur Dent的用户名为favoriteTowel的属性:

myApplication.getUser("Arthur Dent").getProperty("favoriteTowel");

【讨论】:

  • 很好。我喜欢这种方法。它以更多的内存为代价将搜索从 O(n) 减少到 O(2)。从现在开始,我们明确维护用户的身份。在数组中,索引用作用户的身份。但我想这可能是唯一的答案,因为在数组中我们不能将搜索减少到小于 O(n)。
  • @user3212493 很高兴它有帮助!是的,你有正确的想法。没错,数组只是一个使用计数作为键的映射。 :-) 如果您事先知道每个用户的用户 ID,并且您只使用没有间隔的连续数字,那么请确保您可以继续使用数组作为您的支持数据结构......但它仍然是逻辑上的地图地图!此外,O(2) 是常数时间,即 O(1)。大 O 复杂度描述的是上限,而不是精确的步数。
  • 我没有意识到实际的问题。实际上我们不知道用户的名字。所以我们必须搜索所有拥有该属性的用户。
  • 搜索所有拥有该属性的用户...为了什么?如果您不知道用户名,您对他有什么了解?你怎么知道什么时候找到合适的用户?
猜你喜欢
  • 1970-01-01
  • 2019-01-19
  • 1970-01-01
  • 2017-04-07
  • 2013-07-05
  • 2011-10-11
  • 2020-02-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多