ImageVerifierCode 换一换
格式:DOCX , 页数:18 ,大小:193.05KB ,
资源ID:20302024      下载积分:3 金币
快捷下载
登录下载
邮箱/手机:
温馨提示:
快捷下载时,用户名和密码都是您填写的邮箱或者手机号,方便查询和重复下载(系统自动生成)。 如填写123,账号就是123,密码也是123。
特别说明:
请自助下载,系统不会自动发送文件的哦; 如果您已付费,想二次下载,请登录后访问:我的下载记录
支付方式: 支付宝    微信支付   
验证码:   换一换

加入VIP,免费下载
 

温馨提示:由于个人手机设置不同,如果发现不能下载,请复制以下地址【https://www.bdocx.com/down/20302024.html】到电脑端继续下载(重复下载不扣费)。

已注册用户请登录:
账号:
密码:
验证码:   换一换
  忘记密码?
三方登录: 微信登录   QQ登录  

下载须知

1: 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。
2: 试题试卷类文档,如果标题没有明确说明有答案则都视为没有答案,请知晓。
3: 文件的所有权益归上传用户所有。
4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
5. 本站仅提供交流平台,并不能对任何下载内容负责。
6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

版权提示 | 免责声明

本文(Map 综述一彻头彻尾理解 HashMap文档格式.docx)为本站会员(b****6)主动上传,冰豆网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对上载内容本身不做任何修改或编辑。 若此文所含内容侵犯了您的版权或隐私,请立即通知冰豆网(发送邮件至service@bdocx.com或直接QQ联系客服),我们立即给予删除!

Map 综述一彻头彻尾理解 HashMap文档格式.docx

1、, Cloneable, Serializable.三. HashMap 的构造函数HashMap 一共提供了四个构造函数,其中 默认无参的构造函数 和 参数为HashMap的构造函数 为 Java Collection Framework 规范的推荐实现,其余两个构造函数则是 HashMap 专门提供的。1、HashMap()该构造函数意在构造一个具有 默认初始容量 (16) 和 默认负载因子(0.75) 的空 HashMap,是 Java Collection Framework 规范推荐提供的,其源码如下: /* * Constructs an empty HashMap with th

2、e default initial capacity * (16) and the default load factor (0.75). */ public HashMap() /负载因子:用于衡量的是一个散列表的空间的使用程度 this.loadFactor = DEFAULT_LOAD_FACTOR; /HashMap进行扩容的阈值,它的值等于 HashMap 的容量乘以负载因子 threshold = (int)(DEFAULT_INITIAL_CAPACITY * DEFAULT_LOAD_FACTOR); / HashMap的底层实现仍是数组,只是数组的每一项都是一条链 table

3、 = new EntryDEFAULT_INITIAL_CAPACITY; init(); 2、HashMap(int initialCapacity, float loadFactor)该构造函数意在构造一个 指定初始容量 和 指定负载因子 的空 HashMap,其源码如下: * Constructs an empty HashMap with the specified initial capacity and load factor. public HashMap(int initialCapacity, float loadFactor) /初始容量不能小于 0 if (initial

4、Capacity MAXIMUM_CAPACITY) initialCapacity = MAXIMUM_CAPACITY; /负载因子不能小于 0 if (loadFactor = 0 | Float.isNaN(loadFactor)Illegal load factor: + loadFactor); / HashMap 的容量必须是2的幂次方,超过 initialCapacity 的最小 2n int capacity = 1; while (capacity initialCapacity) capacity = 1; /负载因子 this.loadFactor = loadFact

5、or; /设置HashMap的容量极限,当HashMap的容量达到该极限时就会进行自动扩容操作 threshold = (int)(capacity * loadFactor); table = new Entrycapacity;3、HashMap(int initialCapacity)该构造函数意在构造一个指定初始容量 和 默认负载因子 (0.75) 的空 HashMap,其源码如下: / Constructs an empty HashMap with the specified initial capacity and the default load factor (0.75) p

6、ublic HashMap(int initialCapacity) this(initialCapacity, DEFAULT_LOAD_FACTOR); / 直接调用上述构造函数4、HashMap(Map m)该构造函数意在构造一个与指定 Map 具有相同映射的 HashMap,其 初始容量不小于 16 (具体依赖于指定Map的大小),负载因子是 0.75,是 Java Collection Framework 规范推荐提供的,其源码如下: / Constructs a new HashMap with the same mappings as the specified Map. / T

7、he HashMap is created with default load factor (0.75) and an initial capacity / sufficient to hold the mappings in the specified Map. public HashMap(Map m) / 初始容量不小于 16 this(Math.max(int) (m.size() / DEFAULT_LOAD_FACTOR) + 1, DEFAULT_INITIAL_CAPACITY), DEFAULT_LOAD_FACTOR); putAllForCreate(m); 在这里,我

8、们提到了两个非常重要的参数:初始容量 和 负载因子,这两个参数是影响HashMap性能的重要参数。其中,容量表示哈希表中 桶的数量 (table 数组的大小),初始容量是创建哈希表时桶的数量;负载因子是哈希表在其容量自动增加之前可以达到多满的一种尺度,它衡量的是一个散列表的空间的使用程度,负载因子越大表示散列表的装填程度越高,反之愈小。对于使用 拉链法(下文会提到)的哈希表来说,查找一个元素的平均时间是 O(1+a),a 指的是链的长度,是一个常数。特别地,若负载因子越大,那么对空间的利用更充分,但查找效率的也就越低;若负载因子越小,那么哈希表的数据将越稀疏,对空间造成的浪费也就越严重。系统默

9、认负载因子为 0.75,这是时间和空间成本上一种折衷,一般情况下我们是无需修改的。四. HashMap 的数据结构1、哈希的相关概念Hash 就是把任意长度的输入(又叫做预映射, pre-image),通过哈希算法,变换成固定长度的输出(通常是整型),该输出就是哈希值。这种转换是一种 压缩映射,也就是说,散列值的空间通常远小于输入的空间。不同的输入可能会散列成相同的输出,从而不可能从散列值来唯一的确定输入值。简单的说,就是一种将任意长度的消息压缩到某一固定长度的 消息摘要函数 。2、哈希的应用:数据结构我们知道,数组的特点是:寻址容易,插入和删除困难;而链表的特点是:寻址困难,插入和删除容易。

10、那么我们能不能综合两者的特性,做出一种寻址容易,插入和删除也容易的数据结构呢?答案是肯定的,这就是我们要提起的哈希表。事实上,哈希表有多种不同的实现方法,我们接下来解释的是最经典的一种方法 拉链法,我们可以将其理解为 链表的数组,如下图所示:我们可以从上图看到,左边很明显是个数组,数组的每个成员是一个链表。该数据结构所容纳的所有元素均包含一个指针,用于元素间的链接。我们根据元素的自身特征把元素分配到不同的链表中去,反过来我们也正是通过这些特征找到正确的链表,再从链表中找出正确的元素。其中,根据元素特征计算元素数组下标的方法就是 哈希算法。总的来说,哈希表适合用作快速查找、删除的基本数据结构,通

11、常需要总数据量可以放入内存。在使用哈希表时,有以下几个关键点:hash 函数(哈希算法)的选择:针对不同的对象(字符串、整数等)具体的哈希方法;碰撞处理:常用的有两种方式,一种是 open hashing,即 拉链法;另一种就是 closed hashing,即 开地址法(opened addressing)。3、HashMap 的数据结构我们知道,在Java中最常用的两种结构是 数组 和 链表,几乎所有的数据结构都可以利用这两种来组合实现,HashMap 就是这种应用的一个典型。实际上,HashMap 就是一个 链表数组,如下是它数据结构:从上图中,我们可以形象地看出HashMap底层实现还

12、是数组,只是数组的每一项都是一条链。其中参数initialCapacity 就代表了该数组的长度,也就是桶的个数。在第三节我们已经了解了HashMap 的默认构造函数的源码:从上述源码中我们可以看出,每次新建一个HashMap时,都会初始化一个Entry类型的table数组,其中 Entry类型的定义如下:static class Entry implements Map.Entry final K key; / 键值对的键 V value; / 键值对的值 Entry next; / 下一个节点 final int hash; / hash(key.hashCode()方法的返回值 * Cr

13、eates new entry. Entry(int h, K k, V v, Entry n) / Entry 的构造函数 value = v; next = n; key = k; hash = h; .其中,Entry为HashMap的内部类,实现了 Map.Entry 接口,其包含了键key、值value、下一个节点next,以及hash值四个属性。事实上,Entry 是构成哈希表的基石,是哈希表所存储的元素的具体形式。五. HashMap 的快速存取在HashMap中,我们最常用的两个操作就是:put(Key,Value) 和 get(Key)。我们都知道,HashMap中的Key是

14、唯一的,那它是如何保证唯一性的呢?我们首先想到的是用equals比较,没错,这样可以实现,但随着元素的增多,put 和 get 的效率将越来越低,这里的时间复杂度是O(n)。也就是说,假如 HashMap 有1000个元素,那么 put时就需要比较 1000 次,这是相当耗时的,远达不到HashMap快速存取的目的。实际上,HashMap 很少会用到equals方法,因为其内通过一个哈希表管理所有元素,利用哈希算法可以快速的存取元素。当我们调用put方法存值时,HashMap首先会调用Key的hashCode方法,然后基于此获取Key哈希码,通过哈希码快速找到某个桶,这个位置可以被称之为 bu

15、cketIndex。通过Java 中的 =, equals 与 hashCode 的区别与联系 所述hashCode的协定可以知道,如果两个对象的hashCode不同,那么equals一定为 false;否则,如果其hashCode相同,equals也不一定为 true。所以,理论上,hashCode 可能存在碰撞的情况,当碰撞发生时,这时会取出bucketIndex桶内已存储的元素,并通过hashCode() 和 equals() 来逐个比较以判断Key是否已存在。如果已存在,则使用新Value值替换旧Value值,并返回旧Value值;如果不存在,则存放新的键值对到桶中。因此,在 Hash

16、Map中,equals() 方法只有在哈希码碰撞时才会被用到。下面我们结合JDK源码看HashMap 的存取实现。1、HashMap 的存储实现在 HashMap 中,键值对的存储是通过 put(key,vlaue) 方法来实现的,其源码如下: * Associates the specified value with the specified key in this map. * If the map previously contained a mapping for the key, the old * value is replaced. * * param key key with

17、 which the specified value is to be associated * param value value to be associated with the specified key * return the previous value associated with key, or null if there was no mapping for key. * Note that a null return can also indicate that the map previously associated null with key. public V

18、put(K key, V value) /当key为null时,调用putForNullKey方法,并将该键值对保存到table的第一个位置 if (key = null) return putForNullKey(value); /根据key的hashCode计算hash值 int hash = hash(key.hashCode(); / - (1) /计算该键值对在数组中的存储位置(哪个桶) int i = indexFor(hash, table.length); / - (2) /在table的第i个桶上进行迭代,寻找 key 保存的位置 for (Entry e = tablei;

19、 e != null; e = e.next) / - (3) Object k; /判断该条链上是否存在hash值相同且key值相等的映射,若存在,则直接覆盖 value,并返回旧lue if (e.hash = hash & (k = e.key) = key | key.equals(k) V oldValue = e.value; e.value = value; e.recordAccess(this); return oldValue; / 返回旧值 modCount+; /修改次数增加1,快速失败机制 /原HashMap中无该映射,将该添加至该链的链头 addEntry(hash

20、, key, value, i); return null;通过上述源码我们可以清楚了解到HashMap保存数据的过程:首先,判断key是否为null,若为null,则直接调用putForNullKey方法;若不为空,则先计算key的hash值,然后根据hash值搜索在table数组中的索引位置,如果table数组在该位置处有元素,则查找是否存在相同的key,若存在则覆盖原来key的value,否则将该元素保存在链头(最先保存的元素放在链尾)。此外,若table在该处没有元素,则直接保存。这个过程看似比较简单,但其实有很多需要回味的地方,下面我们一一来看。先看源码中的 (3) 处,此处迭代原因

21、就是为了防止存在相同的key值。如果发现两个hash值(key)相同时,HashMap的处理方式是用新value替换旧value,这里并没有处理key,这正好解释了 HashMap 中没有两个相同的 key。1). 对NULL键的特别处理:putForNullKey()我们直接看其源码: * Offloaded version of put for null keys private V putForNullKey(V value) / 若key=null,则将其放入table的第一个桶,即 table0 e = table0; e = e.next) if (e.key = null) /

22、若已经存在key为null的键,则替换其值,并返回旧值 / 快速失败 addEntry(0, null, value, 0); / 否则,将其添加到 table0 的桶中通过上述源码我们可以清楚知到,HashMap 中可以保存键为NULL的键值对,且该键值对是唯一的。若再次向其中添加键为NULL的键值对,将覆盖其原值。此外,如果HashMap中存在键为NULL的键值对,那么一定在第一个桶中。2). HashMap 中的哈希策略(算法)在上述的 put(key,vlaue) 方法的源码中,我们标出了 HashMap 中的哈希策略(即(1)、(2)两处),hash() 方法用于对Key的hashC

23、ode进行重新计算,而 indexFor() 方法用于生成这个Entry对象的插入位置。当计算出来的hash值与hashMap的(length-1)做了&运算后,会得到位于区间0,length-1的一个值。特别地,这个值分布的越均匀, HashMap 的空间利用率也就越高,存取效率也就越好。我们首先看(1)处的 hash() 方法,该方法为一个纯粹的数学计算,用于进一步计算key的hash值,源码如下: * Applies a supplemental hash function to a given hashCode, which * defends against poor quality

24、 hash functions. This is critical * because HashMap uses power-of-two length hash tables, that * otherwise encounter collisions for hashCodes that do not differ * in er bits. * * Note: Null keys always map to hash 0, thus index 0. static int hash(int h) / This function ensures that hashCodes that differ only by / constant multiples at each bit position have a bounded / number of collisions (approximately 8 at default loa

copyright@ 2008-2022 冰豆网网站版权所有

经营许可证编号:鄂ICP备2022015515号-1