结构
数组。
需要size()----大小
需要put(k,v)----放入
需要get(i)----取出
思路
①初始化空间大小为2^n,比如2,4,8,16。
②从节点计算hash&(length-1)得到位置插入,之后计算是否超出阈值(这个阈值由自己决定,是否超出阈值决定了要不要扩容)
对于上面的解释
①hash值不确定,可能会特别大,加入长度为16,hash为11111111
②00001111&11111111=00001111=15
③所有的hash都在当前范围内,但会形成链。
④有人分析了很多得出结论----扩容2倍是最好的,避免了数组空间的浪费,充分利用了空间,减少了碰撞的概率。https://blog.csdn.net/jiary5201314/article/details/51439982
⑤但是个人觉得选择2倍扩容,并且初始为2的倍数,只是为了处理分配空间,扩容重新排序的正常反应。
③如果阈值大于自己的设定值(demo里设最长链长度为b,空间大小为2^n,当b>n)
④新建一个长度为当前二倍的数组空间,数据整理到新的数组中。hashmap的数组变更为新的数组。
⑤继续插入。
代码
public class HashMap<K, V> {
private Node<K, V>[] nodes = new Node[2];
private int len = 2;
private int mi = 1;
private int size;
private int branch;
public int size(){
return size;
}
public void put(K k, V v){
int temp = (len - 1) & k.hashCode();
if (nodes[temp] == null){
nodes[temp] = new Node<>(k, v);
} else {
Node node = nodes[temp];
int i = 1;
while (node != null){
i++;
if (node.k.equals(k)){
node.v = v;
size--;
break;
}
if (node.next == null){
node.next = new Node(k, v);
break;
}
node = node.next;
}
if (i > branch) {
branch = i;
}
}
size++;
if (branch > mi && mi < 31){
sort();
}
}
//内部整理put
private void put(Node[] nodes, K k, V v){
int temp = (nodes.length - 1) & k.hashCode();
if (nodes[temp] == null){
nodes[temp] = new Node<>(k, v);
} else {
Node node = nodes[temp];
while (node != null){
if (node.k.equals(k)){
node.v = v;
size--;
break;
}
if (node.next == null){
node.next = new Node(k, v);
break;
}
node = node.next;
}
}
}
public V get(K k){
int temp = k.hashCode() & (len - 1);
if (temp < size && temp >= 0){
Node node = nodes[temp];
while (node != null) {
if (node.k.equals(k)){
return (V) node.v;
}
node = node.next;
}
}
return null;
}
private void sort(){
Node<K, V>[] newNodes = new Node[len = len * 2];
mi++;
for (int i = 0; i < nodes.length; i++){
if (nodes[i] != null){
put(newNodes, nodes[i].k, nodes[i].v);
Node<K, V> node = nodes[i].next;
while (node != null){
put(newNodes, node.k, node.v);
node = node.next;
}
}
}
nodes = newNodes;
}
public static class Node<K, V>{
public K k;
public V v;
public Node next;
public Node(K k, V v){
this.k = k;
this.v = v;
}
}
}