Java hashmap和数组在查找的时间复杂度上的差异

Java hashmap和数组在查找的时间复杂度上的差异,java,hashmap,Java,Hashmap,如果我必须知道在hashmap中获取值的键(对于时间复杂度O(1)),为什么它与在知道索引(O(1))的情况下在数组中获取值有什么不同 换句话说,hashmap对于查找被认为具有O(1)复杂度,但这是因为键是已知的。当索引已知时,这与数组相同——如果我不知道索引,它将是O(n),这与不知道键相同,对于hashmap也是O(n)(containsValue(Object value)方法) 因此,我不明白为什么hashmap被认为是更有效的查找工具。我认为理解这一点的一个好方法是使用实际用例。假设

如果我必须知道在hashmap中获取值的键(对于时间复杂度O(1)),为什么它与在知道索引(O(1))的情况下在数组中获取值有什么不同

换句话说,hashmap对于查找被认为具有O(1)复杂度,但这是因为键是已知的。当索引已知时,这与数组相同——如果我不知道索引,它将是O(n),这与不知道键相同,对于hashmap也是O(n)(containsValue(Object value)方法)


因此,我不明白为什么hashmap被认为是更有效的查找工具。

我认为理解这一点的一个好方法是使用实际用例。假设您想要存储一个学生的名字和他的分数

因此有两个字段

String name
Integer marks 
现在,您希望根据学生姓名查找分数

在数组方式中,您将创建一个类,该类保存信息并将它们放入数组中

现在要检查学生姓名的标记,您需要迭代整个数组,或者需要知道特定姓名存储在哪个索引处。这两者都是O(N)复杂性

或者,您可以将其存储在以键为名称、以值为标记的地图中。您可以按O(1)复杂度中的名称查找地图


TL;博士您需要查看您的用例,然后决定是否可以使用数组(基于有序索引的查找)或实际上需要一个用于查找的映射

知道数组的索引不同于知道hashmap的键

在数组中,不在数组内容中存储索引。这看起来像

i[0] = 0, i[1] = 1, i[2] = 2, etc...  
实际上,它看起来更像

i[0] = 20, i[1] = 100, i[2] = 5, etc.. 

为了知道包含您要查找的任何元素的数组的索引,您可以存储一个索引数组(即我前面提到的奇怪示例),或者您可以使用一个单独的内存工具将索引映射到数组中的正确元素(本质上是一个hashmap)


hashmap允许您在0(1)次内找到数组中的元素(无需单独的内存中对象将索引映射到元素,也无需映射包含数组索引以外内容的数组)。

当然,这相当于在有索引的情况下查找数组。HashMap不被认为比直接数组索引更有效。它比在数组中搜索特定的密钥更有效,但为什么不呢?在hashmap中搜索特定键或值的效率为O(n),与您给出的示例相同,但hashmap允许您选择索引的内容。因此,为您的用例选择一个相关的索引,并获得o(1)复杂性。数组类似于整数索引,仅限于一个连续的[0,n]空间,这在许多实际用例中是无用的,因此通常不作为索引集使用。当然,如果您有一个在[0,n]上索引有意义的用例,那么是的,数组可能(至少)是性能和hashmap一样。但是为什么hashmap被认为是更快的查找呢?我想我明白了。Hashmap查找本身并不快,但在您这样的情况下,使用它会更容易(您建议的方法仍然可以通过数组和O(1)实现,方法是使用索引命名学生,例如Michael->0、Greg->1等)。然而,我仍然不太适应在教程中我被告知hashmaps是如此有用,因为它们使许多情况更加有效,我觉得仍然缺少一些东西。是的,我可以看出你仍然有些困惑。如果一个程序想要找到“Greg”的分数,它如何知道它必须查看第一个索引?你需要在某个地方存储Greg存储在第一个索引中的映射。如果你的查找键是一个增量计数器,那么你可以使用一个数组并获得类似的O(1)复杂度,除了该映射之外的任何东西都会更好。
i[0] = 'dog', i[1] = 'cat', i[2] = 'parrot', etc...