1.HashMap的存储结构:数组+链表
2.创建这样一个类型的对象
//创建一个节点类,数据域是一个Entry类型的键值对
static class Node<K,V>{
private Entry<K,V> value;
private Node<K,V> next;
public Node(Entry<K, V> value) {
this.value = value;
}
//创建一个Entry类
static class Entry<K,V>{
private K key;
private V value;
public Entry(K key, V value) {
this.key = key;
this.value = value;
}
}
}
3.自定义对象及其一些属性值
private Node[] element;
private final double LOADFATOR=0.75;//扩容因子
private int Node_size;//插入节点的个数
private int array_size;//元素所占数组的实际长度
private final int INTSIZE=16;//数组大小默认设定为16
4.put方法的具体实现
public void put(K key, V value) {
//判断是否该扩容
if ((double)array_size/element.length>LOADFATOR){
Node<K,V>[] newelement=new Node[element.length*2];
rehash(newelement);
element=newelement;
}
//求hashcode值,确定数据存放的位置
int index=key.hashCode()%element.length;
if (element[index]==null){
array_size++;//数组的占用个数
}
//键相同值覆盖
Node.Entry<K,V> entry=containKey0(key);
if (entry!=null){//找到键所对应的值,并替换掉
entry.value=value;
return;
}else {
Node.Entry<K, V> entry1 = new Node.Entry<>(key, value);
Node<K, V> node = new Node<>(entry1);
node.next = element[index];//把node节点的下一个位置指向element[index]保存的地址
element[index] = node;//让element[index]保存现在node的地址
Node_size++;
}
}
5.如果当前占用的实际数组大小/数组大小 > 0.75 就需要进行重新hash
private void rehash(Node<K,V>[] array){
array_size=0;
int index ;
//把原来数组中的数据在新的数组中进行重新定位
for (int i = 0; i <element.length; i++) {
while (element[i]!=null){
Node<K,V> p=element[i];//p变量用来实现节点的删除和在新数组中的插入
element[i]=element[i].next;//把p独立出来
int newIndext=p.value.key.hashCode()%array.length;
if (array[newIndext]==null){//数组当前位置为空,则数组被占的实际大小加一
array_size++;
}
//头插法
p.next=array[newIndext];
array[newIndext]=p;
}
}
}