HashMap除了有无参的构造方法(默认会构造出一个默认为16的数组及loadFactor=0.75的HashMap)外,也可以在New HaspMap的时候指定这两个值。原构造方法声明如下:
HashMap(int initialCapacity, float loadFactor) Constructs an empty HashMap with the specified initial capacity and load factor.
第一个参数:initialCapacity,初始化容量。
第二个参数:loadFactor,重新加载比例。即当Map的容量小于initialCapacity*loadFactor的时候,进行扩容。扩容就意味着重新申请更大的内存,对原来的数据进行重hash。显然是一件很浪费时间的问题。
通常情况下,我们可能需要将一个List里面的东西,转化成一个HashMap来进行进一步的运算。这个时候,我们可以调用List.size获得元素的数量,这样,我们就可以在构造一个HashMap的时候就指定他的大小。
比如:
Map<Long,Object> data = new HashMap<Long,Object>(list.size,1f)
我们认为,这样初始化化HashMap就会省去中间Map因默认的16数组不够导致的resize和rehash,性能会高点。
你可能会认为,如果你这样写,初始化容量就是list.size。
那你就大错特错了。我们看看HashMap的源码:
// Find a power of 2 >= initialCapacity int capacity = 1; while (capacity < initialCapacity) capacity <<= 1; //此处的意思就是不断的加倍扩展 this.loadFactor = loadFactor; threshold = (int)Math.min(capacity * loadFactor, MAXIMUM_CAPACITY + 1); table = new Entry[capacity];
从代码可以看出,hashMap的大小只可能是2,4,8,16,32,128,....1024......等大小,也就是2的n次方大小,如果你的list里面不幸是129个元素,那么HashMap就会创建一个256的数组。就是这么悲催。
不过,指定大小肯定比不知道大小,性能要高点。
static int indexFor(int h, int length) { return h & (length-1); }
好了,写这个纯粹为一时兴起。但这个同时也引起了我对另一个问题的探索,就是String的hashcode重复的概率。
因为String的hashcode,代码是这样:
public int hashCode() { int h = hash;//默认0 if (h == 0) { int off = offset;//默认0 char val[] = value;//字符串是用字符数组表示的. int len = count;//字符串长度 for (int i = 0; i < len; i++) { h = 31*h + val[off++]; } hash = h; } return h; }
哪个问题,我就再写一篇吧。
参考资料:
http://blog.csdn.net/sgbfblog/article/details/7580510
http://donlianli.iteye.com/blog/1978237
相关推荐
在Java中,HashMap的初始化涉及两个重要属性:initialCapacity(初始容量)和loadFactor(负载因子)。initialCapacity定义了HashMap的初始大小,而loadFactor定义了在何时进行扩容的阈值。默认情况下,...
1. **初始化**:可以无参数或指定容量和加载因子初始化HashMap。例如: ```java HashMap, String> map = new HashMap(); HashMap, String> map2 = new HashMap(16, 0.75f); ``` 2. **添加元素**:使用`put()`...
HashMap在创建时会初始化一个默认容量(16)和负载因子(0.75)。当元素数量达到当前容量与负载因子的乘积时,HashMap会自动进行扩容,通常新容量为原容量的两倍。这个过程涉及到数组的复制,可能会带来一定的性能...
- **初始化散列表**:创建大小为`capacity`的`Entry[]`数组作为散列表,并设置`useAltHashing`标志以决定是否启用替代散列算法。 #### 四、总结 `HashMap`通过结合数组和链表(或红黑树)的数据结构,在保持高效的...
可以看到,putVal 方法首先判断 table 数组是否为空,如果为空,则调用 resize 方法将其初始化。resize 方法会将 table 数组的容量和阈值都扩大为原来的2倍。 接下来,putVal 方法会根据 key 的hashCode计算出要...
- 初始化数据结构:使用数组作为基础存储结构,因为数组可以通过索引来直接访问元素,速度很快。但由于哈希冲突的存在,我们还需要一个链表或红黑树来处理冲突。 - 计算哈希码:对于输入的键,我们需要调用其...
这个构造函数初始化一个新的`HashMap`实例,并调用`clear`方法来清除内部存储的数据。这样做的目的是确保每次创建新的`HashMap`实例时,它都是空的、干净的状态。 ##### `clear`: 清除所有条目 `public function ...
- **初始化**:初始化`HashSet`时可以指定初始容量,例如`new HashSet(17)`。 #### 五、总结 综上所述,`HashTable`、`HashMap`和`HashSet`各有其特点和适用场景: - 如果需要线程安全,并且不允许`key`或`value`...
初始化时,HashMap并不会立即创建数组,而是先计算阈值threshold,它是容量的负载因子倍数。threshold的计算使用了tableSizeFor()函数,确保其为2的幂次方。 2. **tableSizeFor()函数**: 这个静态函数接收一个...
构造函数`public analyetest()`初始化了所有的`HashMap`和`ArrayList`对象。这些对象用于存储词法分析过程中识别出来的各种符号。 ##### 2.3 初始化方法 - **init()**: 调用四个子方法来初始化不同类型的符号。 - ...
HashMap的构造函数包括HashMap(int initialCapacity, float loadFactor),它传入初始化容量和加载因子作为参数,如果初始化容量小于0将抛出异常,如果初始化容量大于最大容量就把它设为最大容量。 HashMap的Entry是...
HashMap是一个动态变长的数据结构,在使用HashMap的时候,为了提高执行效率,我们往往会设置HashMap初始化容量: ```java Map,String> rm=new HashMap,String>(2) ``` 或者使用guava的工具类Maps,可以很方便的创建...
本教程将深入分析2022年Java中HashMap的内部机制、关键属性和操作。 HashMap的核心属性包括容量(capacity)和负载因子(load factor)。容量是指HashMap可以存储的元素的最大数量,而负载因子则是HashMap在达到多...
HashMap的全局变量定义了其核心参数,包括默认初始容量(16)、最大容量(2^30)、默认负载因子(0.75)以及树化和去树化的阈值(分别为8和6)。负载因子定义了在达到多大比例的填满时应该进行扩容,而树化和去树化...
1. 如果数组`table`为空,这意味着HashMap尚未初始化,putVal会触发`resize()`方法进行初始化,创建一个大小为16的新数组。 2. 根据key的哈希值计算出对应的数组索引`i`。如果该位置的数组元素为null,直接将新节点`...
初始化长度为16LoadFactor:负载因子,默认值为0.75f 6. 扩容的步骤 扩容分为两步:扩容:创建一个新的Entry空数组,长度是原数组的2倍。ReHash:遍历原Entry数组,把所有的Entry重新Hash到新数组。 7. 为什么要重新...
初始化容量是哈希表中桶的数量,加载因子衡量了HashMap在自动扩容前能有多满。默认的加载因子0.75是一个平衡空间利用率和查找效率的折衷选择。 3. **数据结构** HashMap的核心数据结构是“链表散列”,即数组与...
初始化哈希表时,需要为数组和链表分配内存。同时,为了防止内存泄漏,插入和删除元素后记得释放不再使用的内存。 5. **跨平台兼容性**:为了使哈希表能在Windows和Linux上运行,需要注意以下几点: - 文件操作:...
3. **数据流分析**:通过跟踪函数间的调用关系和数据流动,理解HashMap的结构是如何被初始化、更新和查询的。这可能涉及到对指针解引用、内存布局的理解以及动态分析。 4. **哈希函数分析**:HashMap的关键在于它的...