假设我们有两个不同的hashMap,分别是map1和map2。
假设我们有一个对象“ obj1”,其哈希码为“ 1234”,并将该对象作为键同时放在map1和map2(值“ xyz”)中。
在map2中查找“ obj1”值是否需要更多时间? 从map1和map2访问obj1的时间复杂度是否仍为O(1)?
答案 0 :(得分:3)
在resetAuth
中查找存储桶总是O(1),与容量(存储桶数)无关。
假设您的HashMap
的哈希码为obj1
。 1234567
的核心不是要搜索正确的存储桶(如TreeMap那样),而是要计算其位置,并立即使用该数字访问存储桶。那就是哈希码进入游戏的地方。
计算为HashMap
,结果数字给出了obj.hashCode() % capacity
的索引。
对于小型哈希图,其为bucketsArray
= 1234567 % 1000
,这意味着相关的存储段为567
。
对于大个子来说,它是bucketsArray[567]
= 1234567 % 999999
,结果是234568
。
除法值的计算所需的时间是恒定的,与值无关。具有给定索引的数组的访问时间也是固定的,因此为O(1)。
我们只是在谈论寻找水桶。如果存储桶包含多个条目,则线性搜索将完成哈希映射访问,即O(K),其中K为存储桶中条目的(平均?最大?)个数。
答案 1 :(得分:3)
我想最好用代码和图表来回答。我们都知道它是什么(单向)哈希函数。基本上,它接受任意输入并返回数字(在Java中为int,但并非总是如此)。 Java中的int有32位。这意味着它可以在-2,147,483,648和2,147,483,647之间。存在的每个Java堆上的每个对象都可以计算其哈希值(使用java.util.Object类中的方法),并且它必须处于该间隔内。
现在让我们假设我们有3个对象。
21234 = obj1.hashCode();
623424 = obj2.hashCode();
23124432 = obj3.hasCode();
,我们想将它们添加到具有200个存储桶的hashMap中。 (这不是我在这里输入的有效的Java代码)
public class MyHashMap {
private final Buckets[] buckets = new Buckets[200];
public boolean add(Object object){
int resultModulo = object.hashCode() % 200;
buckets[buckets].add(object);
}
}
现在争取最后的和平。对于我们的对象,resultModulo
将为34(21234),24(623424),32(23124432)。计算的数量不会超过200。
数组被分配为连续的内存。只是指针数组(64位)而不是实际对象。所以bucktes []看起来像这样
0xB80000xB80020xB80670xC1101 ....
1 2 3 4 .... 200
所以当您的代码调用bucket [34],bucket [24],bucket [32]时,硬件的作用是这样的:
mov eax, bucktes[ecx*19]
; eax now contains the pointer to the
; 19 element in the array
; this is a one clock instruction
所以这就是为什么有多少个桶都没关系的原因。