分析了一下HashMap这个类后,发现实现机制也挺简单的。当然里面的散列函数比较复杂,还没看明白,但大致就是那么回事了。
首先散列的快速读取是基于数组的,所以,先定义一个数组,存放Entry,大小由capacity决定,默认为16。
当调用put(key,value)函数时
1,key调用自身对象的hashcode函数,返回一个int值A。
2,对A进行一次包装hash(A)返回hash值B。这个B会被存储起来。
3,indexFor(B)方法返回int值C,这个C就是即将要保存的最初定义数组中的索引。
indexFor中使用(B & leng -1)使得返回的值始终小于leng(leng为2的幂值)。
4,此处有点绕,得看完Entry定义才能明白。
Enry有四个东西需要保存:hash值,key,value,next Entry。
因为数组大小是一定的,不能无限扩容,所以就利用了链表,一个数组元素里放了一个Entry,当需要存到相同数组元素中时,会把占了位的Entry对象搬出来,然后新建一个Entry对象,这个对象指向原先的对象(新Entry.next Entry = 原Entry)。
理论上讲,不管数组多大,都是可以的,程序照样运行,但链表的检索效率太低,所以,定义了factor即所谓的负载因子,默认为0.75,当负载过大时,会扩容,扩大为原先的2倍,这样可以避免链表过长。
比如,使用默认的构造函数new HashMap()时,数组长度为16,负载因子0.75,当数组中有12个元素时(大于等于12),进行resize,使得数组长度为32。
当负载因子越小,越容易达到扩容的条件,数组元素中的链表就越短,查询速度就会越快,但会增加重散列的开销。
这个数组的长度一定是2的幂值,我的理解就是方便使用indexFor函数,理论上最好是质数,这里特殊,Java编程思想中也有提到。
另外还有两个问题
1,key值为null时,直接存放到数组的第一个元素,即索引为0。
2,当在Entry链表中发现相同key值时,利用equals方法进行比较,相同则覆盖value或取出value。
所以,若干本书上强调,当某个类当散列结构的key时,一定得重写hashcode和equals函数,因为,Object类的hashcode是基于内存地址计算的,相同的对象会返回不同的值。而不同的对象也会产生相同的hashcode,所以得再利用equals函数,进行判定。
分享到:
相关推荐
通过`hashCode()`和`equals()`的合理使用,以及数组和链表的结合,HashMap实现了高效的键值对存储和查找。了解这些实现细节对于优化代码性能和避免潜在问题至关重要。在实际编程中,应充分考虑哈希冲突的处理、负载...
这篇博客“基于JavaScript的HashMap实现”可能详细阐述了如何通过自定义函数来创建一个高效且灵活的HashMap数据结构。 在JavaScript中,对象(Object)是哈希表的一种表现形式,其内部通过键(key)来定位值(value...
在这个系统中,使用HashMap实现是一种高效且灵活的方法,因为HashMap提供了快速的查找和插入操作。本文将深入探讨如何使用HashMap来构建一个电话本管理系统,并通过源码分析增强理解。 HashMap是Java集合框架中的一...
"基于HashMap的用户标签处理兼Java中HashMap实现原理研究" 本文研究了基于HashMap的用户标签处理方法,并对Java中HashMap的实现原理进行了深入研究。HashMap是一种高效的数据结构,可以快速地存储和检索数据。本文...
在resize()方法的实现中,我们可以看到HashMap使用了power-of-two expansion机制,即每次扩容时,数组的长度都会翻倍。这使得HashMap的扩容机制更加高效。同时,在resize()方法中,我们还可以看到HashMap使用了 ...
HashSet是基于HashMap实现的。它内部维护了一个HashMap,用于存储实际的元素。HashSet不保证元素的顺序,且不允许有重复元素。当向HashSet添加元素时,元素实际上会被存入内部的HashMap,键是添加的元素,值是一个...
总结来说,JavaScript的HashMap实现主要依赖于内置对象的特性,通过自定义类可以创建自己的HashMap实例,进行各种操作。在实际开发中,理解并合理运用HashMap能帮助我们编写更高效、更简洁的代码。
在使用HashMap时,需要注意几个关键点:1) 键必须正确实现hashCode()和equals()方法,以确保哈希计算和比较的一致性;2) 避免使用null键和null值,因为HashMap的null键和null值有特殊含义;3) 考虑负载因子和初始...
HashMap类在Java编程...在阅读《HashMap1.js》和《HashMap.js》这两个文件时,可以深入分析其JavaScript版本的HashMap实现,虽然与Java版本可能有所不同,但基本的哈希映射原理是相通的,有助于拓宽对哈希表的理解。
Java使用HashMap实现并查集 Java使用HashMap实现并查集是指使用Java语言中的HashMap数据结构来实现并查集。并查集是一种树型的数据结构,用于处理一些不相交集合(Disjoint Sets)的合并及查询问题。常常在使用中以...
在Java编程中,HashMap是一个非常重要的数据结构,它实现了Map接口,提供了键值对的存储功能,具有快速存取和高效查找的特点。HashMap基于哈希表(也称为散列表)原理,通过键对象的哈希码来定位元素,进而实现O(1)...
与HashSet的区别在于,HashSet是基于HashMap实现的集合类,用于存储唯一对象。HashSet中的元素没有顺序,添加元素时,HashSet会将元素转化为键放入HashMap中。因此,HashSet的插入和查找速度与HashMap相当,但由于...
### HashMap的实现原理 #### 1. HashMap概述 HashMap 是 Java 集合框架中一个非常重要的类,它实现了 Map 接口,并提供了基于哈希表的存储方式。与其它 Map 实现不同的是,HashMap 允许使用 `null` 键和 `null` 值...
HashMap实现了Map接口,提供了所有映射操作。它不保证映射的顺序,尤其在多线程环境下,映射的顺序可能会发生变化。HashMap通过哈希函数来计算键(key)在数组中的位置,以便快速访问。 2. **数据结构**: HashMap...
HashMap 源码实现红黑树添加元素和删除元素 HashMap 中使用红黑树来存储元素,是为了提高查找、插入和删除操作的性能。红黑树是一种自平衡二叉树,可以保持二叉树的平衡,从而获得较高的查找性能。 红黑树的创建...
在Java编程语言中,`HashMap`是一个非常常用的数据结构,它实现了`Map`接口,用于存储键值对。`HashMap`使用哈希表实现,提供快速的插入、删除和查找操作。当我们需要遍历`HashMap`中的所有元素时,通常会使用`...
HashMap 的存储实现可以通过查看其 put(K key, V value) 方法的源代码来了解。该方法首先判断 key 是否为 null,然后根据 key 的 hashCode 值计算 Hash 值,接着搜索指定 hash 值在对应 table 中的索引,如果 i 索引...
1. 使用迭代器遍历:使用 iterator() 方法取得 HashMap 的迭代器,然后使用 hasNext() 和 next() 方法遍历 HashMap 中的元素。 2. 使用 foreach 遍历:使用 foreach 语句遍历 HashMap 中的元素。 HashMap 的常用...