package cn.map;
import java.util.ArrayList;
import java.util.List;
public class MyHashMap<K, V> implements MyMap<K,V>{
//数组表默认长度
private static int defaultLength = 16;
//负载因子
private static double defaultLoader = 0.75;
//存储元素的表
private Entry<K, V>[] table = null;
//数组中存取元素的个数
private int size = 0;
public MyHashMap() {
this.table = new Entry[defaultLength];
}
public MyHashMap(int length, double loader) {
this.defaultLength = length;
this.defaultLoader = loader;
this.table = new Entry[defaultLength];
}
//这是一个hash算法,根据K对表的长度取余,得到的值就是表的下标
private int getIndex(K k) {
int m = defaultLength;
//得到的可能是一个负值
int index = k.hashCode() % m;
return index >= 0 ? index : -index;
}
@Override
public V put(K k, V v) {
if(size >= defaultLength * defaultLoader) {
upSize();
}
//根据k拿到存储位置,hash计算
int index = getIndex(k);
Entry<K, V> entry = table[index];
if(entry == null) {
size++;
}
table[index] = newEntry(k, v, entry);
return table[index].getValue();
}
//扩容方法,每次扩充一倍
private void upSize() {
Entry<K,V>[] newTable = new Entry[2 * defaultLength];
//数组长度翻倍,元素在表中的位置也要随之改变
reHash(newTable);
}
//新建数组,然后把旧数组中的元素再次进行hash
private void reHash(Entry<K,V>[] newTable) {
List<Entry<K,V>> list = new ArrayList<>();
//把旧表中的全部数据放到list中
for(int i = 0; i < table.length; i++) {
if(table[i] == null) {
continue;
}
addEntryByNext(table[i], list);
}
//再次hash
if(list.size() > 0) {
size = 0;
defaultLength *= 2;
table = newTable;
for(Entry<K,V> entry : list) {
if(entry.next != null) {
//将原始链表结构全部解体
entry.next = null;
}
put(entry.getKey(),entry.getValue());
}
}
}
//将entry所在链表数据全部放入指定list中
private void addEntryByNext(Entry<K,V> entry, List<Entry<K,V>> list) {
if(entry != null && entry.next != null) {
list.add(entry);
addEntryByNext(entry.next, list);
} else {
list.add(entry);
}
}
private Entry<K, V> newEntry(K k, V v, Entry<K,V> next) {
return new Entry(k, v, next);
}
@Override
public V get(K k) {
int index = getIndex(k);
if(table[index] == null) {
return null;
}
return findEntryByEqKey(k,table[index]);
}
//根据key在entry链表中查找对应元素的value
private V findEntryByEqKey(K k, Entry<K, V> entry) {
if(k == entry.getKey() || k.equals(entry.getKey())) {
return entry.getValue();
} else {
if(entry.next != null) {
return findEntryByEqKey(k, entry.next);
}
}
return null;
}
@Override
public int size() {
// TODO Auto-generated method stub
return 0;
}
class Entry<K, V> implements MyMap.Entry<K, V> {
K k;
V v;
//next指针,指向下一个链表数据
Entry<K, V> next;
public Entry(K k, V v, Entry<K, V> next) {
this.k = k;
this.v = v;
this.next = next;
}
@Override
public K getKey() {
return this.k;
}
@Override
public V getValue() {
return this.v;
}
}
}
JDK中的HashMap具有更加复杂的位运算,大大提高了元素的命中率,所以效率会比简化版HashMap快,但是HashMapd的基本原理就是这样
手写HashMap简化版
最新推荐文章于 2023-09-14 10:06:08 发布