最近阅读了HashMap的源码,为了加深对HashMap的理解自己动手仿写了一个HashMap,
主要实现了get(),put(),resize()方法。具体的说明在代码的注释里。
public class MyHashMap<K,V> {
private Node<K,V>[] table;
private int size=0;
private int capacity;
private float loadFactor;
/**
* @Description: 无参构造
* @Param: []
* @return: []
* @Author: Kwg
* @Date: 2022/4/11
*/
public MyHashMap() {
this.capacity = 16;
this.loadFactor = 0.75f;
/**
* table = new Node<K,V>[capacity];
* 直接这样会报错,Java是不支持实例化泛型数组的,
* 因为Java认为数组是不可变的,而泛型数组中的元素类型是会变化的,
* 一个解决方法,利用反射就可以实例化一个固定大小的泛型数组了
*/
table = (Node<K, V>[]) Array.newInstance(Node.class,capacity);
}
/**
* @Description: 自定义容量,负载因子的构造器
* @Param:
* @return:
* @Author: Kwg
* @Date: 2022/4/11
*/
public MyHashMap(int initialCapacity,float loadFactor){
//自定义容量不能小于0
if(initialCapacity<0){
throw new IllegalArgumentException("不合法容量:"+capacity);
}
//自定义负载因子不能小于等于0并且不能是NaN值
if(loadFactor<=0||Float.isNaN(loadFactor))
throw new IllegalArgumentException("不合法负载因子"+loadFactor);
//容量自定义向上取2的n次方
this.capacity=tableSizeFor(initialCapacity);
this.loadFactor=loadFactor;
table = (Node<K, V>[]) Array.newInstance(Node.class,capacity);
}
//容量自定义向上取2的n次方
static final int tableSizeFor(int cap){
int n = cap - 1;
n |= n >>> 1;
n |= n >>> 2;
n |= n >>> 4;
n |= n >>> 8;
n |= n >>> 16;
return (n < 0) ? 1 : n + 1;
}
/**
* 计算hash值
*/
int Hash(K key){
return Objects.hashCode(key)^(Objects.hashCode(key)>>>16);
}
/**
* 计算对应的下标
* @param hash
* @return
*/
int Index(int hash){
int len=this.table.length;
return (len-1)&hash;
}
/**
* 核心方法put方法
* @param key
* @param value
*/
void put(K key,V value){
int hash=Hash(key);
int index=Index(hash);
//判断是发送覆盖的标记,有false,无true
boolean flag=true;
Node<K,V> node=new Node<>(key,value,hash);
if(this.table[index]==null){
table[index]=node;
}else {
Node<K,V> head=this.table[index];
//搜素链表
while (head!=null){
//key相等则覆盖
if(key== head.key){
head.value=value;
flag=false;
break;
}
//尾插法
if(head.next==null){
head.next=node;
break;
}
head=head.next;
}
}
if(flag) this.size++;
if(size>capacity*loadFactor) resize();
}
/**
* 核心方法 get
* @param key
* @return
*/
V get(K key){
V value=null;
int hash=Hash(key);
int index=Index(hash);
if(this.table[index]==null){
return value;
}else {
Node<K,V> head=this.table[index];
//遍历所有节点
while (head!=null){
if(head.key==key){
value= head.value;
break;
}
head=head.next;
}
return value;
}
}
/**
* 扩容
*/
void resize(){
//老的table
Node<K,V>[] oldTable=this.table;
//长度*2
this.table=(Node<K, V>[]) Array.newInstance(Node.class,2*capacity);
this.capacity*=2;
for(int i=0;i<oldTable.length;i++){
if(oldTable[i]!=null){
Node<K,V> head=oldTable[i];
while (head!=null){
put(head.key, head.value);
head=head.next;
}
}
}
}
public int getSize(){
return size;
}
class Node<K,V>{
K key;
V value;
int hash;
Node<K,V> next;
public Node(K key,V value,int hash){
this.hash=hash;
this.key=key;
this.value=value;
}
}
}