HashMap


import org.junit.Test;

import java.util.HashMap;
/*
hash表:顺序表+链表

顺序表:
顺序表每存储一个元素,就要开辟一个空间
顺序表有长度限制,如果全部采用顺序表存储会造成空间的浪费

链表:
不限长度,查找元素比较慢,采用顺序表+链表存储

hash表如何进行数据存储:
1.计算一个对象的hash码
2.对hash码进行散列处理,尽量避免hash冲突
3.会采用处理后的hash码 & 顺序表长度-1

1.7jdk map
DEFAULT_INITIAL_CAPACITY =16 默认的顺序表的长度
static final int MAXIMUM_CAPACITY = 1 << 30; 顺序表的最大长度
static final float DEFAULT_LOAD_FACTOR = 0.75f;默认的加载因子
Entry<K,V>[] table; 顺序表的数据类型
class Entry<K,V> implements Map.Entry<K,V> {
int hash;
final K key;
V value;
Entry<K,V> next;
}
transient int size; 集合中元素的数量
int threshold;阈(开关/阈门)值

顺序表什么时候扩容
1.当size>=阈值,初始化长度*加载因子
2.要存入的位置有数据
进行扩容,扩容规则 2*table.length,加载因子如果太小,会造成顺序表太长,空间浪费,加载因子如果太大,链表太长,影响查询元素效率


一.当创建完对象后
底层Entry类型的数组已经完成初始化,长度为16
阈值的值是12
加载因子0.75f

二.调用put方法
2.1 如果key为null
会将数据存储到顺序表中下标为0的位置
如果已经存在key为null的数据,则直接用新数据替换旧数据,并将旧数据返回

2.2 key不为null
调用hash方法对key进行散列算法,拿到hash值
indexFor(hash,数组的长度);计算在hash表内顺序表的位置

2.2.1 当指定位置有数据时
有重复数据:
1.有key重复数据,则将新的value数据替换到旧的value数据,并将旧的value数据返回

没有重复数据:
新增一个节点,并将此节点放到顺序表中的第一个位置,之前的旧数据会在新数据的后面进行追加




* */
public class Demo6 {
@Test
public void test1(){
HashMap<Integer,String> map = new HashMap<>();
map.put(null,"你好");
System.out.println(map);//{null=你好}
map.put(1,"世界");
System.out.println(map);//{null=你好, 1=世界}
map.put(null,"广大");
System.out.println(map);//{null=广大, 1=世界}
}
}

jdk1.7是采用顺序表+链表
jdk1.8是采用顺序表+链表+红黑树(二叉树),当链表的数量>8的时候,会转为红黑树进行存储

创建完对象之后,将加载因子给成员变量赋值,没有给底层数组进行开辟空间

调用put()
1.第一步对key进行hash运算
  注意:如果key==null,h:0
       如果key!=null,进行位运算,为了减少hash冲突
2.当第一调用put()完成了对底层数组的创建Node[] 长度是16,阈值变为12

3.1当第一次向指定位置添加数据的时候,此位置没有数据,直接新增

3.2当第二次添加,存储的位置是有值的
    key不重复,直接原有数据的末尾进行元素的追加
    key不重复,链表的数量已经达到8并且底层数组的长度已经大于64,才会进行树化操作

 

posted @ 2022-01-19 10:59  从此重新定义啦  阅读(29)  评论(0编辑  收藏  举报