map实现的思想是散列 hash;

数组的特点是查询快,增删慢,而链表的特点是查询慢,增删快;

map本身也是hash表的一种实现

map的具体实现 是 数组加上单向链表, 就是一个数组(位桶数组,为了实现散列,默认长度16),每个元素都是一个链表(Node);node由hashcode码(底层编码),键值对,next 组成; 最后得到的是 Node[] table;

一般过程是:

通过key值得到hashcode(比如35125162213很长一串);通过取余算法来得到一个hash值(p<16),根据p值来决定链表的存放在数组的位置,如果余数相同(称为碰撞),这个时候就要放到链表的next上了。 这样就能 查询和增删效率都高。

这是一般过程,我们来说两种极端的算法,

极端的算法1: 算法是hashcode/hashcode ,这样总是一, 整体上就会退化成一个很长的链表。

极端的算法2:不采用散列,建一个非常大的数组,每个hashcode 都是单独一个元素位置映射;这样就会导致结构退化成数组。

(1)最早的Hashtable 就是采用去余数的算法, (2)但是效率太低下,散列效率低,后来jdk 改进了算法

// 当前的算法使用的 & ,这样取余得到的结果是一样的, 但是效率提高了
// 首先要预定数组的长度是2的整数幂;

hash值 = hashcode &  (数组长度-1);

(3)然后在这个基础上又进行了一次散列目的 就是为了更加均匀的分布,提升最好的效率。

map底层实现原理java map内部实现原理_链表

(4) jdk 8中,链表的长度大于8的时候就转换为红黑树,这样更加增加了查询 效率;

 

**********************************

取数过程get(key)

1,通过传入的key ,拿到hashcode,通过hash() 散列算法得到hash值(位桶数组的index);这样就的得到一个链表

2,在通过和链表的每一个key 做比较(key.equals()),true则返回结果, java中.equals() 本质上是比较hashcode,

*************************

扩容问题

hashmap的位桶数组的初始大小是16个,如果到了0.75*数组长度的时候,那么就会数组大小扩容到原来的两倍。

扩容很耗时间,本质是定义更大的数组,并将旧数组拷贝到新数组中

************************

jdk 8以上链表长度大于8,将链表转为红黑二叉树;