各个版本的hashmap的底层实现

package com.liuyuan.test07;

import java.util.HashMap;

import org.junit.Test;


/*
 * 一、JDK1.6的HashMap:数组+链表
 * (1)new HashMap()
 * table数组初始化为了一个长度为16的空数组,threshold=12
    public HashMap() {
        this.loadFactor = DEFAULT_LOAD_FACTOR;//0.75
        threshold = (int)(DEFAULT_INITIAL_CAPACITY * DEFAULT_LOAD_FACTOR);//12
        table = new Entry[DEFAULT_INITIAL_CAPACITY];//16
    }
 * 
 * 二、几个常量与变量的介绍
 * 1、DEFAULT_INITIAL_CAPACITY:16
 * 2、DEFAULT_LOAD_FACTOR:0.75		默认加载因子
 * 3、threshold:阈值/临界值       数组需要考虑扩容的阈值	
 * 		threshold = capacity(容量,数组的长度) * load factor(加载因子,默认是0.75)
 * 		例如:	 threshold = 16 * 0.75  当数组大概3/4满的时候就考虑扩容
 *  思考:load factor设置为0.9和0.1有什么区别?
 *  	0.1:扩容太频繁
 *  	0.9:会导致table[index]下面的链表会很长,查询速度就低
 * 
 * 三、JDK1.7的HashMap:数组+链表
 * 1、new HashMap()
 * table数组初始化为了一个长度为0的空数组
 *  
 * 2、 put()
 * 步骤:
 * (1)发现数组table是空数组后,会把数组初始化为长度为16的Entry类型的数组,并且把threshold计算为12
 * 这里如果你手动指定了数组的capacity,那么如果这个capacity不是2的n次方,会自动纠正为2的n次方
 * 
 * 为什么要纠正为2的次方?
 * ①后面算index = hash & table.length-1,这样才能保证[0,table.length-1]范围内
 * ②2的次方,根据它的散列算法,可以保证比较均匀的分散在它的数组的各个位置
 * 
 * (2)如果key是null,特殊对待,key为null的映射关系的hash值为0,index也为0
 * 
 * (3)hash = hash(key) 
 * 为了干扰我们key的hashCode值
 * 
 * (4)index = hash & table.length-1
 * (5)先判断table[index]下面是否有映射关系的key是和我新添加的映射关系的key有重复的,如果有,就用新的value替换旧的value,就结束了
 * (6)如果没有重复的,决定添加新的映射关系
 * ①看是否需要扩容
 * 扩容的条件:A:size达到阈值threshold  B:table[index]下面已经有映射关系,即不为空
 * 如果扩容了,会重新计算hash和index
 * 
 * ②把新的映射关系new为一个Entry的对象,放到table[index]中,原来table[index]的映射关系作为新的映射关系的next连接起来。
 * 
 * Entry相当于是一个结点类型。是一个单向链表的结点类型。
 * class Entry{
 * 		int hash;
 * 	    Object key;
 * 		Object value;
 * 		Entry next;
 * }
 * 
 */
@SuppressWarnings("all")
public class TestHashMap7 {
	@Test
	public void test(){
		HashMap map = new HashMap();
		
		map.put(null, "aa");
		map.put("Aa", "bb");
		map.put("BB", "bb");
		map.put("A", "xx");
		map.put("B", "xx");
		
		for (int i = 0; i < 15; i++) {
			map.put(i+"", "xx");
		}
	}
	
	@Test
	public void test2(){
		System.out.println("Aa".hashCode());//2112
		System.out.println("BB".hashCode());//2112
	}
}

/*
 * Map的底层实现是什么?
 * 1、哈希表系列:
 * 		数组 + 链表
 * 		数组 + 链表/红黑树
 * 2、TreeMap:红黑树
 * 
 * HashMap的底层实现:
 * 		JDK1.7以及之前:数组 + 链表
 * 		JDK1.8以及之后:数组 + 链表/红黑树
 * 
 * 数组的优点:访问速度快,因为可以根据下标直接定位到某个元素
 * 链表的优点:不需要元素是挨着存储,不需要连续空间,在添加和删除元素时不需要移动元素,只需要修改前后元素的引用关系就可以。
 * 		HashMap:会根据key的hashCode-->公式/算法-->[index]
 * 			    因为不同的hashCode值,可能得到的[index]是相同的,那么此时就冲突了,那么只能把[index]的多个映射关系用链表连接起来
 * 二叉树的优点:查找的速度比链表快
 * 		旧版的HashMap,如果key的hashCode算出了[index]相同的话(我们称为冲突)都在一个table[index]下面,
 * 	    	如果严重的话,会导致[index]下面的链表很长,就会导致查询速度减慢。当链表长到一定程度时,就需要把链表变为二叉树,以提高我们查询速度。
 * 
 */

 

转载于:https://my.oschina.net/architectliuyuanyuan/blog/3089513

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值