HashMap的创建与插入
来源:互联网 发布:mac qq input 编辑:程序博客网 时间:2024/06/06 06:53
在讲HashMap的创建之前,我们先看一个例子(这个例子是修改于360公司2016校招笔试的一个选择题):
package test.hashmap;import java.util.HashMap;public class TestHashMap { public static void main(String[] args) { HashMap<String,Integer> hsTest= new HashMap<String,Integer>(); hsTest.put("young", 22); hsTest.put("young", 23); hsTest.put(null, 0); System.out.println("the size of hsTest is " + hsTest.size()); }}
大家觉得,这个程序的输出结果是多少呢?
HashMap的创建
HashMap是基于数组创建的,HashMap最核心的结构是 transient Entry<K,V>[] table
,这个是真正存储HashMap数据的结构,也就是说,我们存在HashMap中的数据就是存在这个数组里头的,既然是数组,那么问题来了,数组的大小是多少呢?如果我们一直往里面增加数据的时候,那数组的容量够用吗?
在new HashMap的时候,会调用HashMap的无参构造函数,而无参构造函数会调用另外一个具有两个参数的构造函数 public HashMap(int initialCapacity, float loadFactor)
,前一个参数是HashMap的初始化大小,也就是刚才提到的数组大小,即在创建HashMap的时候,会自动创建一个大小长度为initialCapacity的数组table,值得一提的是,如果没有指定数组table的初始化大小,则数组table的初始化大小默认为16,那么,细心的同学可能马上都注意到了,大小才16?没错,只有16,但是,请放心,我们再看后一个参数loadFactor,它是装载因子,和initialCapacity一样,可以在构造函数中指定大小,如果没有指定的话,则默认值为0.75,意思就是,如果当前数组中实际存储的元素个数与数组长度的比值达到0.75时,数组长度会翻一倍。也就是,当数组实际存储量达到0.75时,数组的长度就会自动扩充一倍,所以,我们不用担心,HashMap的长度会随着我们存储的数量增大而自动变长,那么长度最大是多少呢,答案是1<<32。
HashMap的插入
在使用HashMap时,我们要往其中插入数据,这个时候会用到put方法,这个方法可以往HashMap中插入键/值对,如果存在当前要插入的键,则用当前的键/值对替换之前的数据。接下来看下HashMap put 的源代码,如下:
public V put(K key, V value) { if (key == null) return putForNullKey(value); //解释(1) int hash = hash(key); //解释(2) int i = indexFor(hash, table.length); //解释(3) for (Entry<K,V> e = table[i]; e != null; e = e.next) { Object k; if (e.hash == hash && ((k = e.key) == key || key.equals(k))) { V oldValue = e.value; e.value = value; e.recordAccess(this); return oldValue; } }//解释(4) modCount++; addEntry(hash, key, value, i); //解释(5) return null; }
(1):在HashMap中,我们可以往其中插入为null的key,判断key是否为空,如果为空,则调用putForNullKey函数,putForNullKey的功能为是,查找原来HashMap中key为null的项,如果存在,则用当前的value,替换原来的value,并返回原来的value。如果不存在,则插入。之所以要单独处理,是因为如果不为null,我们需要对key进行hash映射,计算key的hash值,找到当前key在HashMap中的位置,而key为null的时候,直接默认key的hash值为0。
(2):根据某种hash算法,计算key的hash值。
(3):根据key的hash值与hash表的长度,计算当前这个key在hash表中的索引。
(4):这个for循环的功能是:在原来的HashMap中,查找是否存在我现在正要插入的这个key,如果存在,则把此key对应的原来的value用当前这个value替换,并返回旧的value。值得注意的是,从for循环中可以发现,HashMap虽然是基于数组的,但同时也是基于链表的,因为我们知道,Hash表有可能会起冲突,即key的hash值一样,如果我们仅采用数组,那么当hash值一样时,在一个数组元素中,我们不可能存储两个值,因此,HashMap不仅基于数组,也基于链表,即先通过key的hash值,找到key在数组中的位置,然后每个hash相同的key又采用链表存储,因此,我们在用key的hash值定位到数组的位置时,仍然还要使用for循环来查找链表里是否真的存在当前这个key,从for中可以看到,e=e.next,就是找下一个节点。
(5):前面的几个相当于,都是在做前期准备工作,判断key不是null,也确定当前这个key在HashMap中没有存储,接下来就是往这个HashMap插入这个键/值对。
讲解到了这里,上面那个例子就so easy了。
1、可以在HashMap中插入key为null的键/值对。
2、在HashMap中插入数据时,如果存在相同key,则用新的value替换旧的value
因此,上面的输出结果为 2
顺便说一句,HashMap不是线程安全的。
小结
1)HashMap的初始大小为16,装载因子为0.75,当数组的装载量达到装载因子时,则HashMap的大小自动扩充一倍,可以达到的最大容量为1<<32
2)HashMap可以插入key为null的键
3)HashMap在插入的时候,如果遇到相同的key,则用新的value替换旧的value
4)HashMap是基于数组的,不同的hash的key存在数组的不同位置,相同hash的key采用链表连接起来
5)HashMap不是线程安全的
- HashMap的创建与插入
- 链表的创建与插入练习
- 单链表的创建插入与删除
- 顺序表的创建插入与删除
- 二叉排序树的插入创建与查找
- HashMap的相关笔记----创建HashMap
- java HashMap的插入操作源码分析
- HashMap 中插入null key 的过程
- 数据结构实验--线性表的创建与插入
- 双向循环链表的创建,插入与删除。
- SPJ 与 Student 数据库的创建于数据插入
- opencv创建序列cvCreateSeq与插入元素cvSeqPush的运用
- C++实现哈希表的创建,销毁,键值插入与删除
- 每天一点数据结构之二叉树的插入与创建
- jQuery中的DOM节点的创建与多种插入方式
- C语言-动态链表的创建遍历与插入
- 树的创建、插入
- HashMap与HashTable的区别、HashMap与HashSet的关系
- OC_UIImagePicker_系统相册
- 第0000道练习题_Python简单图像处理
- 虚函数那些小事儿(一)
- hdu 1532 Drainage Ditches 增广路 ford
- 多线程のPV操作(厨师->【馒头】->消费者)过程
- HashMap的创建与插入
- Struts2学习笔记--HelloWorld!(2015.8.11)
- 黑马程序员
- cocos ide 出现连接ide超时的原因和解决办法
- 深入理解Java虚拟机(1)虚拟机内存区域划分 与内存溢出异常
- arm的v7体系结构
- POJ1661 Help Jimmy ----- 动态规划
- 记Android里的坐标
- ubuntu mysql 备份 卸载 升级