jdk7 HashSet和HashMap源码分析
先来看看HashMap的一些成员变量以及他们的含义
- /**
- * The default initial capacity - MUST be a power of two.
- */
- static final int DEFAULT_INITIAL_CAPACITY = 16;//默认Entry数组的长度
- /**
- * The load factor used when none specified in constructor.
- */
- static final float DEFAULT_LOAD_FACTOR = 0.75f;//加载因子,和数组长度有关
- /**
- * The table, resized as necessary. Length MUST Always be a power of two.
- */
- transient Entry<K,V>[] table;//HashMap底层实现就是Entry数组,以后说的数组就是这个数组
- /**
- * The number of key-value mappings contained in this map.
- */
- transient int size; //添加元素的个数
HashSet的底层实现就是用HashMap实现的。
hashset的add方法就是用hashmap的put方法。key是添加的元素,value是hashset维护的一个常量。这里不多说了,主要还是分析HashMap的源代码。
- public V put(K key, V value) {
- if (key == null)
- return putForNullKey(value);//添加键为null的元素
- int hash = hash(key);//得到key的hash值,这个hash值是对key的hashcode进行过处理的
- int i = indexFor(hash, table.length);//根据hash值和数组长度得到元素保存到数组中的位置
- 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))) {
- //根据hashcode和equals方法判断键是否重复了,如果键重复了,将值替换了,并返回原来的值。
- V oldValue = e.value;
- e.value = value;
- e.recordAccess(this);
- return oldValue;
- }
- }
- //如果键不重复,则添加到数组中
- modCount++;
- addEntry(hash, key, value, i);//hash值,键,值,插入到数组的位置(索引)
- return null;
- }
- /**
- * Offloaded version of put for null keys
- */
- private V putForNullKey(V value) {
- for (Entry<K,V> e = table[0]; e != null; e = e.next) {
- if (e.key == null) {//添加的key为null,如果已经存在key为null的元素,则替换原来的值,返回旧值
- V oldValue = e.value;
- e.value = value;
- e.recordAccess(this);
- return oldValue;
- }
- }
- modCount++;
- addEntry(0, null, value, 0);//添加第一个key为null的元素
- return null;
- }
- //可以看出,添加key为null的元素每次都是添加到数组的第一个位置,重复添加key为null的元素,新值替换旧值
- void addEntry(int hash, K key, V value, int bucketIndex) {
- if ((size >= threshold) && (null != table[bucketIndex])) {
- resize(2 * table.length);//如果元素个数大于threshold(这个数是一个数乘以加载因子,与加载因子相乘的这个数与初始化数组长度有关) 扩容为原来的两倍
- hash = (null != key) ? hash(key) : 0;
- bucketIndex = indexFor(hash, table.length);//得到一个新的位置
- }
- createEntry(hash, key, value, bucketIndex);
- }
- void createEntry(int hash, K key, V value, int bucketIndex) {
- Entry<K,V> e = table[bucketIndex];//得到存在数组中该位置的元素
- table[bucketIndex] = new Entry<>(hash, key, value, e);//将新添加的元素存到该位置上,并关联之前保存在该位置上的数组
- size++;//元素个数+1
- }
- static class Entry<K,V> implements Map.Entry<K,V> {
- final K key;
- V value;
- Entry<K,V> next;
- int hash;
- /**
- * Creates new entry.
- */
- Entry(int h, K k, V v, Entry<K,V> n) {
- value = v;
- next = n;
- key = k;
- hash = h;
- }
- ...
- }
- //Entry的结构
总结:当添加key为null的元素,会保存在数组的第一个位置上。其他key不为null的情况,是根据key的hash值来判断保存都Entry数组中的位置,如果该位置上没有元素,则直接添加。如果数组中已经在该位置上有元素了,根据hashcode和equals方法来判断键是否重复,如果重复,则替换旧值,并返回旧值。如果不重复,则将新元素添加到数组的索引上,然后通过Entry的next属性关联之前保存在该位置上的元素。当元素的个数大于某个值(不作详解)且该位置上有元素时,数组长度扩容为原来的两倍。
上面是添加元素,下面是取元素。
- public V get(Object key) {
- if (key == null)
- return getForNullKey();//获取键为null的值
- Entry<K,V> entry = getEntry(key);//根据key获取元素
- return null == entry ? null : entry.getValue();
- }
- private V getForNullKey() {
- for (Entry<K,V> e = table[0]; e != null; e = e.next) {
- if (e.key == null)
- return e.value;//返回key为null的值
- }
- return null;//如果不存在key为null,则返回null
- }
- final Entry<K,V> getEntry(Object key) {
- int hash = (key == null) ? 0 : hash(key);//得到key的hash值
- for (Entry<K,V> e = table[indexFor(hash, table.length)];
- e != null;
- e = e.next) {//根据key的hash值来索引保存在数组中的位置,如果索引到的位置有元素,判断key是否一致,直到判断完该位置上的所有元素,如果都不匹配,则返回null。如果该位置上没有元素,则返回null。
- Object k;
- if (e.hash == hash &&
- ((k = e.key) == key || (key != null && key.equals(k))))
- return e;
- }
- return null;//不存在key则返回null
- }
jdk7 HashSet和HashMap源码分析的更多相关文章
- HashSet底层HashMap源码分析
在看HashSet源码的时候,意外发现底层HashMap保存的value居然不是null,而是保存一个Object作为Value.顿觉有悖常理,于是来分析一下: HashSet的add方法: publ ...
- Java HashMap源码分析(含散列表、红黑树、扰动函数等重点问题分析)
写在最前面 这个项目是从20年末就立好的 flag,经过几年的学习,回过头再去看很多知识点又有新的理解.所以趁着找实习的准备,结合以前的学习储备,创建一个主要针对应届生和初学者的 Java 开源知识项 ...
- HashMap源码分析和应用实例的介绍
1.HashMap介绍 HashMap 是一个散列表,它存储的内容是键值对(key-value)映射.HashMap 继承于AbstractMap,实现了Map.Cloneable.java.io.S ...
- Java HashSet和HashMap源码剖析
转自: Java HashSet和HashMap源码剖析 总体介绍 之所以把HashSet和HashMap放在一起讲解,是因为二者在Java里有着相同的实现,前者仅仅是对后者做了一层包装,也就是说Ha ...
- 【JAVA集合】HashMap源码分析(转载)
原文出处:http://www.cnblogs.com/chenpi/p/5280304.html 以下内容基于jdk1.7.0_79源码: 什么是HashMap 基于哈希表的一个Map接口实现,存储 ...
- Java中HashMap源码分析
一.HashMap概述 HashMap基于哈希表的Map接口的实现.此实现提供所有可选的映射操作,并允许使用null值和null键.(除了不同步和允许使用null之外,HashMap类与Hashtab ...
- JDK1.8 HashMap源码分析
一.HashMap概述 在JDK1.8之前,HashMap采用数组+链表实现,即使用链表处理冲突,同一hash值的节点都存储在一个链表里.但是当位于一个桶中的元素较多,即hash值相等的元素较多时 ...
- 【Java】HashMap源码分析——常用方法详解
上一篇介绍了HashMap的基本概念,这一篇着重介绍HasHMap中的一些常用方法:put()get()**resize()** 首先介绍resize()这个方法,在我看来这是HashMap中一个非常 ...
- 【Java】HashMap源码分析——基本概念
在JDK1.8后,对HashMap源码进行了更改,引入了红黑树.在这之前,HashMap实际上就是就是数组+链表的结构,由于HashMap是一张哈希表,其会产生哈希冲突,为了解决哈希冲突,HashMa ...
随机推荐
- 关于MEF
MEF(Managed Extensibility Framework)是.NET Framework 4.0一个重要的库,Visual Studio 2010 Code Editor的扩展支持也是基 ...
- 删除重复&海量数据
08. 删除重复&海量数据 重复数据,通常有两种:一是完全重复的记录,也就是所有字段的值都一样:二是部分字段值重复的记录. 一. 删除完全重复的记录完全重复的数据,通常是由于没有设置主键/ ...
- web前端安全---读书笔记
web前端安全---读书笔记 粗略的看完了Web前端黑客技术揭秘前两章了,由于自身的前端功力不深,当然也是初涉前端的安全问题,所以实话还是有些问题看不太明白的.在豆瓣看到的这本书,名字真心有点很肥主流 ...
- rabbitmq在mac上安装
1.安装brew 打开http://bash.sh 执行 ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/ ...
- Ubuntu 下的环境变量配置
网上很多配置jdk环境变量的方法,但是几乎都会下次重启电脑就失效,或者时不时的失效.下面教你一招 JDK环境变量配置如下: 执行命令sudo gedit /etc/environment,在打开的编辑 ...
- [置顶] vs2008 编译adb 支持4.2 android 系统(改进版)
QQ: 2506314894 本想晚些时候放出来的,但是按捺不住啊,所以修改了之后就立即放出来了.先说明一下,这次用的adb 的源码比较新的,用的vs2008 编译出来,只有一个exe 文件,直接就可 ...
- hdu 4515 年月份模拟题
小Q系列故事——世界上最遥远的距离 Time Limit: 500/200 MS (Java/Others) Memory Limit: 65535/32768 K (Java/Others) ...
- .Net程序员学用Oracle系列(7):视图、函数、过程、包
<.Net程序员学用Oracle系列:导航目录> 本文大纲 1.视图 1.1.创建视图 2.函数 2.1.创建函数 2.2.调用函数 3.过程 3.1.创建过程 3.2.调用过程 4.包 ...
- 使用TypeScript开发ReactNative应用的简单示例
最近小小尝试了下 ReactNative + TypeScript 开发APP,爬了无数坑之后总算弄出来个结果,重要的地方记录下,后面会附上示例代码: 1.开发工具的选择 windows 平台我接触的 ...
- 一键强制修改任意Mysql数据库的密码,修改任意环境Mysql数据库。
本文采用我软件里面的内置改密功能,可以一键强制修改Mysql数据库的密码, 在修改过程中,会强制干掉Mysql主程序,修改完成后重新启动Mysql就可以了. 首先讲解如何一键强制修改PHPWAMP自身 ...