Java Hashmap容量与时间的权衡

Java Hashmap容量与时间的权衡,java,hashmap,Java,Hashmap,我有一个非常直截了当的问题,但我想不出来。问题是: 如果我们增加map内部数组的大小(即map的容量),它将增加执行时间(对于put&get方法)?是: 根据这个基准,通常地图越大,你对它做的任何事情都会变得越慢。为每个作业选择正确的地图可以帮助缓解这一问题 如果您只谈论容量,而不是大小,那么您可能正在寻找这个基准:是: 根据这个基准,通常地图越大,你对它做的任何事情都会变得越慢。为每个作业选择正确的地图可以帮助缓解这一问题 如果您只谈论容量,而不是大小,那么可能您正在寻找的就是这个基准:简短回

我有一个非常直截了当的问题,但我想不出来。问题是:

如果我们增加map内部数组的大小(即map的容量),它将增加执行时间(对于
put
&
get
方法)?

是:

根据这个基准,通常地图越大,你对它做的任何事情都会变得越慢。为每个作业选择正确的地图可以帮助缓解这一问题

如果您只谈论容量,而不是大小,那么您可能正在寻找这个基准:

是:

根据这个基准,通常地图越大,你对它做的任何事情都会变得越慢。为每个作业选择正确的地图可以帮助缓解这一问题


如果您只谈论容量,而不是大小,那么可能您正在寻找的就是这个基准:

简短回答:

,唯一影响
put
get
时间的是
hashCode
实现

这个实现为基本操作(get和put)提供了恒定的时间性能,假设哈希函数将元素正确地分散在存储桶中

这种影响发生在你有一个。当两个不同的对象具有相同的哈希代码时,就会发生这种情况


HashMap将根据hashCode计算位置,如果您设置了一个小的initialCapacity和一个非常大的loadFactor,它将发生哈希冲突,因此它将在某些位置创建一个列表。这意味着
get
将运行崩溃元素列表,而不是所有列表

因此,假设您有一个M个元素的N个位置的数组。在最坏的情况下,它将是
O(最大(1,M/N))
。所以
N
应该大于
M

如果查看,如果大小太大(占总容量的75%),它将调用resize操作。因此,初始容量不是最终容量,随着地图的增长,容量将始终更大

初始容量的唯一问题是在需要之前存储内存。这可能会导致内存泄漏

void addEntry(int hash, K key, V value, int bucketIndex) {
    Entry<K,V> e = table[bucketIndex];
    table[bucketIndex] = new Entry<K,V>(hash, key, value, e);
    if (size++ >= threshold)
        resize(2 * table.length);
}
void addEntry(整数散列、K键、V值、整数bucketinex){
条目e=表[bucketIndex];
表[bucketIndex]=新条目(散列、键、值、e);
如果(大小+>=阈值)
调整大小(2*表格长度);
}

简短回答:

,唯一影响
put
get
时间的是
hashCode
实现

这个实现为基本操作(get和put)提供了恒定的时间性能,假设哈希函数将元素正确地分散在存储桶中

这种影响发生在你有一个。当两个不同的对象具有相同的哈希代码时,就会发生这种情况


HashMap将根据hashCode计算位置,如果您设置了一个小的initialCapacity和一个非常大的loadFactor,它将发生哈希冲突,因此它将在某些位置创建一个列表。这意味着
get
将运行崩溃元素列表,而不是所有列表

因此,假设您有一个M个元素的N个位置的数组。在最坏的情况下,它将是
O(最大(1,M/N))
。所以
N
应该大于
M

如果查看,如果大小太大(占总容量的75%),它将调用resize操作。因此,初始容量不是最终容量,随着地图的增长,容量将始终更大

初始容量的唯一问题是在需要之前存储内存。这可能会导致内存泄漏

void addEntry(int hash, K key, V value, int bucketIndex) {
    Entry<K,V> e = table[bucketIndex];
    table[bucketIndex] = new Entry<K,V>(hash, key, value, e);
    if (size++ >= threshold)
        resize(2 * table.length);
}
void addEntry(整数散列、K键、V值、整数bucketinex){
条目e=表[bucketIndex];
表[bucketIndex]=新条目(散列、键、值、e);
如果(大小+>=阈值)
调整大小(2*表格长度);
}
虽然有一些“微优化”,但您通常需要关注的是

这通常取决于可能发生的碰撞次数。为了在Java中正确使用它,您需要重写hashCode()方法。但是请注意,如果这样做,还应该重写equals()方法

一个快速信息为什么

还要注意的是,尽管最好的情况是O(1),最坏的情况是O(n),但是覆盖hashCode()方法的正确实现将产生比您最初根据最佳情况和最坏情况的情况发表意见时的简短观察结果要好得多的性能

从理论上讲,如果您有更多的总组合(用您的话来说:“映射的容量”),您实际上可能会减少潜在哈希代码冲突的数量,因为只有当您有非常大的对象集时,才会希望实际增加,潜在哈希代码组合的增加可能会减少总体执行时间。

虽然存在一些“微优化”,但您通常需要注意的是

这通常取决于可能发生的碰撞次数。为了在Java中正确使用它,您需要重写hashCode()方法。但是请注意,如果这样做,还应该重写equals()方法

一个快速信息为什么

还要注意的是,尽管最好的情况是O(1),最坏的情况是O(n),但是覆盖hashCode()方法的正确实现将产生比您最初根据最佳情况和最坏情况的情况发表意见时的简短观察结果要好得多的性能

从理论上讲,如果你有更多的总组合(用你的话说:“地图的容量”),你实际上很可能会