/*
*@description: Map接口定义
*@author: winyinghouse
*@date:2021/3/7
*/
public interface Map<K,V> {
V put(K k ,V v);
V get(K k);
void resize();
interface Entry<K,V>{
}
}
/*
*@description: HashMap实现
*@author: winyinghouse
*@date:2021/3/7
*/
public class HashMap<K, V> implements Map<K,V> {
Entry<K,V> table[] = null;
int length;
int size;
//默认值
final int DEFAULT_LENGTH =16;
final double LOADFACTOR = 0.75;
/*
构造方法
*/
public HashMap() {
this.table = new Entry[DEFAULT_LENGTH];
this.length = DEFAULT_LENGTH;
this.size = 0;
}
/*
put方法
*/
@Override
public V put(K k, V v) {
int index = hash(k);
Entry<K,V> entry = table[index];
if(entry == null){
table[index] = new Entry<>(k,v,k.hashCode(),null); //若桶没有结点,则直接放进去
}
else{
Entry<K,V> p = table[index];
//这里while也是在寻找是否有相同的key值的结点,有就覆盖value值,其实可以直接调用findequalsk方法
//只是两者实现不同,这里是循环,findequalsk是递归实现。
while(p!=null){
if(p.getKey() == k || p.getKey().equals(k)){
p.setV(v);
return p.getValue();
}
p = p.next;
}
//若不存在,则直接头插法
table[index] = new Entry<>(k,v,k.hashCode(),table[index]);
}
size++; //数量+1
if(size>((length * LOADFACTOR)) && table[index] != null ) { //1.7扩容条件,数量超过阈值,并且存在哈希冲突
resize(); //扩容
index = hash(k); //再算一下扩容后的结点所在的索引
}
return table[index].getValue(); //返回插入结点的value
}
/*
get函数
*/
@Override
public V get(K k) {
if(size == 0){
return null;
}
int index = hash(k);
if(table[index] != null) {
return findequalsk(table[index],k); //寻找
}
return null;
}
/*
扩容函数
*/
@Override
public void resize() {
size = 0;
Entry<K,V> p;
int oldLength = length;
Entry<K,V>[] oldTable = table;
length = oldLength * 2; //数组长度扩大到原来2倍
table = new Entry[length]; //初始化扩容的数组
int i = 0;
//遍历旧数组
while(i<oldTable.length){
p = oldTable[i];
//遍历旧数组上的桶
while(p !=null){
int newIndex = p.getHash()%length;
Entry<K,V> temp = p;
p = p.next; //头插法会破坏连接关系,保留插入前的下一个结点
put(temp.getKey(), temp.getValue()); //将元素一个一个放入新数组
}
i++;
}
}
//递归找到相同key的结点
private V findequalsk(Entry<K,V> p, K k) {
if(p.getKey() == k || p.getKey().equals(k)){
return p.getValue();
}
if(p.next != null){
return findequalsk(p.next,k);
}
return null;
}
//直接就是求索引的函数,没有扰动处理
private int hash(K k){
int index = k.hashCode()%length;
return index > 0? index:-index; //hashcode可能为负数
}
/*
1.7hashmap内部类Entry
*/
class Entry<K,V> implements Map.Entry<K,V>{
K k;
V v;
int hash;
Entry<K,V> next;
public void setK(K k) {
this.k = k;
}
public void setV(V v) {
this.v = v;
}
public int getHash() {
return hash;
}
public void setHash(int hash) {
this.hash = hash;
}
public Entry(K k, V v, int hash, Entry<K,V> next) {
this.k = k;
this.v = v;
this.hash = hash;
this.next = next;
}
public K getKey() {
return k;
}
public V getValue() {
return v;
}
}
}