HashMap不是线程安全的。
那在哪些特定情况下会有线程安全的问题? 扩容(put)
HashMap的数据结构是什么?(即:底层是怎么实现的?实现的原理是什么?)---数组、链表、红黑树
JDK8对HashMap优化哪块? 数组+链表 --->数组+链表+红黑树
怎么去了解它的技术本质?
存储内容:key value
存储结构:数组+链表+红黑树(JDK8)
存储位置:数组下标
存储大小:数组长度
数组:
数组的特点是:
java.util 下面的ArrayList用到的是数组
链表:
链表的特点:
java.util 下面的LinkedList用到的是链表,双向链表
HashMap Entry对象
作用:加快查找速度
为什么Entry对象里面有一个hash值?这个是干什么的?
只有上面这种情况,hash值才一样
手写实现
/**
* 定义接口
*/
public interface Map<K,V> {
public V put(K k , V v);
public V get(K k);
public int size();
public interface Entry<K,V>{
public K getKey();
public V getValue();
}
}
/**
* ClassName: MyHashMap
* Package: PACKAGE_NAME
**/
public class MyHashMap<K,V> implements Map<K,V>{
//定义一个存储空间(数组)
private Entry<K,V>[] table = null;
//定义一个初始的容量
private static int defalutLenth = 16;
//定义一个初始的大小
private int size = 0;
//定义一个构造方法
public MyHashMap(){
//初始化table
table = new Entry[defalutLenth];
}
@Override
public V put(K k , V v){
//hash() 出来hash值
int index = hash(k);
//数组的长度 index值 即下标的位置
//通过这个位置找到我们的table对应的Entry对象
Entry entry = table[index];
//判断一下这个值存不存在
if(null == entry){
//如果为空,就直接填进去就可以了
table[index] = new Entry(k,v,null,index);
size++;
}else{
//如果存在了,用链表
table[index] = new Entry(k,v,entry,index);
}
return table[index].getValue();
}
private int hash(K k){
int index = k.hashCode()%(defalutLenth-1);
return Math.abs(index);
}
@Override
public V get(K k){
if(size==0){
return null;
}
//hash() 出来hash值
int index = hash(k);
//数组的长度 index值 即下标的位置
//通过这个位置找到我们的table对应的Entry对象
Entry<K,V> entry = getEntry(k ,index);
//拿到这个元素,判断一下
return entry==null ? null : entry.getValue();
}
private Entry getEntry(K k , int index){
for(Entry e=table[index];e!=null;e=e.next){
if(e.hash == index && (k==e.getKey() || k.equals(e.getKey()))){
return e;
}
}
return null;
}
@Override
public int size(){
return size;
}
class Entry<K,V> implements Map.Entry<K,V>{
private K k;
private V v;
private Entry<K,V> next;
private int hash;
//构造函数
public Entry(K k , V v , Entry<K,V> next, int hash){
this.k = k;
this.v = v;
this.next = next;
this.hash = hash;
}
@Override
public K getKey(){
return k;
}
@Override
public V getValue(){
return v;
}
}
}
1.8用红黑树解决了平衡性
JDK8 红黑树 解决链表查找快速,但也带了一个问题:插入变慢O(n)。所以jdk8有一个阈值(TREEIFY_THRESHOLL = 8)