理解HashMap

一、深入理解HashMap

HashMap的存储结构:Node {key, value, next}
HashMap中的常量:

//default_inital_capacity:初始容量
static final int DEFAULT_INITIAL_CAPACITY = 1 << 4; // aka 16
//最大容量
static final int MAXIMUM_CAPACITY = 1 << 30;
//负载因子
static final float DEFAULT_LOAD_FACTOR = 0.75f;
//用来确定何时将解决 hash 冲突的链表转变为红黑树
//treeify_threshold
static final int TREEIFY_THRESHOLD = 8;
// 用来确定何时将解决 hash 冲突的红黑树转变为链表
//untreeify_threshold
static final int UNTREEIFY_THRESHOLD = 6;

1.1 怎样确定HashMap的initialCapacity

initialCapacity=[(需要存储元素个数N)/(负载因子loadFactor)]+1
初始化容量–>得到真正的容量–>一定是2的幂次方

initialCapacity为初始化容量
n = initialCapacity-1   
将n的二进制分别向右移2,4,8,18做异或转变为高位全为1,再加1,就得到2的幂次方且小于等于初始化容量。

1.2 谈谈HashMap的数据结构

HashMap数据结构是数组+链表,一个节点包含了Node{hash,key,value,next}

数组+链表:在单个节点的节点长度<8,链表结构{x,data, y}

数组+红黑树:长度>8 & 数组大小>=64;红黑树节点<6,转换为链表

1.3 HashMap的put方法

关键词:

红黑树什么时候扩容:加入节点之后判断是否大于阈值

1.对key计算hash值,将key求hash值,为32位的int值,再计算下标;
2.hash值作为数组坐标:若没有碰撞,放入桶中;若碰撞,放在链表,若链表长度>=8,将转化为红黑表;
3.若节点存在就替换值;
4.若桶容量满了(init * load),就扩容。

1.4 HashMap中的hash()方法的实现

异或:^,两个值不同为0,相同为1;
与:&,两个值都为1才为1;
1.key 的hash()值,按hash高16位与低16位异或计算:[(h = key.hashCode()) ^ (h >>> 16)]--扰动函数,尽可能减少hash碰撞;
2.取模:(n-1)&hash得到下标:tab[i = (n - 1) & hash]。

1.5 HashMap解决冲突以及扩容

1.当计算的hash值相同,将新节点添加链表后;
2.扩容为之前的两倍,对每个节点重新计算hash值;
3.新值的坐标只在两个地方:原坐标或者(原下标+原容量)。

1.6 抛开HashMap,hash冲突的解决方案

  • 开放定址、链地址法
二、HashMap的线程安全性

hashMap是线程不安全的,线程安全有hashTable,Collections.synchronizedMap,ConcurrentHashMap:;

hashTable:在hash的基础上,增加了synchronized锁;
Collections.synchronizedMap:添加了内部锁;
ConcurrentHashMap:使用分段锁。

2.1 谈谈ConcurrentHashMap的实现原理:

1.concurrentHashMap的成员节点使用volatile修饰的,避免了重排序,同时保证了内存可见性;
2.另外使用CAS操作和synchronized结合实现赋值操作,多线程操作只会锁住当前操作索引的节点;

2.2 说说ConcurrentHashMap的CAS的实现以及synchronized的实现原理

D:\gupao_luban\xin\2019-05-19_ConcurrentHashMap的原理分析
E:\2.Study\06\网易微专业\微专业 - Java高级开发工程师(完整版)1\源码课件\网易高级java配套课件代码\subject-1\subject-1\subject-1-docs\1-多线程并发编程\1.3.3-并发容器类Map
四、有序的hashMap

LinkedHashMap与TreeMap

1.LinkedHashMap:内部维护了单链表
2.TreeMap:TreeMap是按照Key的自然顺序或者Comprator的顺序进行排序,内部是通过红黑树来实现。所以要么key所属的类实现Comparable接口,或者自定义一个实现了Comparator接口的比较器,传给TreeMap用户key的比较
五、从集合开始说起

5.1 集合总概

5.2 Java集合的快速失败机制 “fail-fast”

线程A在遍历集合,线程B修改了集合,那么这时候就会抛出ConcurrentModificationException,从而产生‘fail-fast’机制。
可以使用CopyOnWriteArrayList来代替(线程安全)。

5.3 迭代器Iterator

1.集合在自带的迭代器:Iterator itertor = list.iterator();
2.list的移除错误操作:list.remove(list.get(0));而是使用iterator移除iterator.remove();

List的遍历的方式和原理

List的遍历的方式有3中:for,foreach,iterator:Iterator 是面向对象的一个设计模式;
for:基于计数器;
foreach:foreach 内部也是采用了 Iterator 的方式实现;
iterator:Iterator 是面向对象的一个设计模式

RandomAccess 接口

Java Collections框架有个Random Access接口,实现了该接口则采用位置读取
如果实现了该集合,说明支持按位置读取数据,时间复杂度为O(1)--->ArrayList;
如果没实现,则使用LinkedList;

5.4 各种集合的优缺点

1.ArrayList 底层是数组实现的,支持随机访问,它实现了Random Access接口,虽然没有实现具体的方法,但它的查询、添加速度非常快,而插入、删除就很慢;
适用于顺序添加、随机访问的情况。
2.LinkedList 底层是双向链表实现的,所以删除、插入的速度很快,查询慢;它的底层是Node节点实现的,比ArrayList的占用的内存大。

将数组转换为真正的ArrayList?

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值