手工实现HashMap ,包括get() put() remove() size()方法,当然,这是线程不安全的,不过可以学习。
本文代码是在https://blog.csdn.net/weixin_43003240/article/details/87534836 这篇文章上进行改进的,其博客的71行
iterLast = newNode; 这个是有问题的,要对链表进行插入才行,此作者直接进行赋值,如果你用很多个元素进行测试,可以看到,此作者运行出的结果最大只有16个,就是因为没有对链表进行插入。因此,本文对其进行改进如下(也就是三行代码的事情):
//采用头插法进行插入元素 Node2 first = table[newNode.hash]; newNode.next = first; table[newNode.hash] = newNode;
package com.itisyue.base.map;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
class Node2 {
int hash;
Object key;
Object value;
Node2 next;
}
public class MyHashMap {
private Node2[] table;//位桶数组。bucket array
private Long size=0L;//存放的键值对的个数
public MyHashMap() {
table = new Node2[16];//长度一般定义成2的整数幂
}
public Object get(Object key) {
int hash = myHash(key.hashCode(), table.length);
Object value = null;
if (table[hash] != null) {
Node2 temp = table[hash];
while (temp != null) {
if (temp.key.equals(key)) {//如果相等,则说明找到了键值对,返回相应的value
value = temp.value;
break;
} else {
temp = temp.next;
}
}
}
return value;
}
public void put(Object key, Object value) {
//定义新的节点对象
Node2 newNode = new Node2();
newNode.hash = myHash(key.hashCode(), table.length);
newNode.key = key;
newNode.value = value;
newNode.next = null;
Node2 temp = table[newNode.hash];
Node2 iterLast = null;//正在遍历的最后一个元素
boolean keyRepeat = false;
if (temp == null) {
//此处数组元素为空,则直接将新节点放进去
table[newNode.hash] = newNode;
size++;
} else {
//此处数组元素不为空。则遍历对应链表。。
while (temp != null) {
//判断key如果重复,则覆盖
if (temp.key.equals(key)) {
keyRepeat = true;
System.out.println("key重复了!");
temp.value = value;//只是覆盖value即可。其他的值(hash,key,next)保持不变。
break;
} else {
//key不重复,则遍历下一个
iterLast = temp;
temp = temp.next;
}
}
if (!keyRepeat) {
//采用头插法进行插入元素
Node2 first = table[newNode.hash];
newNode.next = first;
table[newNode.hash] = newNode;
//iterLast = newNode;
size++;
}
}
}
public Object remove(Object key) {
//定义新的节点对象
Node2 newNode = new Node2();
newNode.hash = myHash(key.hashCode(), table.length);
newNode.key = key;
newNode.value = "";
newNode.next = null;
Node2 temp = table[newNode.hash];
Node2 preNode = null;//key匹配的前一个节点
boolean keyRepeat = false;
if (temp == null) {
return null;
} else {
preNode = temp;
Long current = 0L;
//此处数组元素不为空。则遍历对应链表。。
while (temp != null) {
//判断key相等
if (temp.key.equals(key)) {
if(current==0L){
//说明是第一个元素
table[newNode.hash].next = temp.next;
}else{
preNode.next = temp.next;//删除当前节点
}
size--;
return temp.value;
} else {
//key不相等,则遍历下一个
preNode = temp;
temp = temp.next;
current++;
}
}
}
return null;
}
public Long size(){
return size;
}
public static int myHash(int v, int length) {
System.out.println(v+" hash in myHash:" + (v & (length - 1)));
//System.out.println(v+" hahs in myHash:" + (v % (length - 1)));
return v & (length - 1);
}
@Override
public String toString() {
StringBuilder sb = new StringBuilder("{");
//遍历bucket数组
for (int i = 0; i < table.length; i++) {
Node2 temp = table[i];
StringBuilder sb1 = new StringBuilder("{");
//遍历链表
while (temp != null) {
sb.append(temp.key + ":" + temp.value + ", ");
sb1.append(temp.key + ":" + temp.value + ", ");
temp = temp.next;
}
if(sb1.length()>1){
sb1.setCharAt(sb1.length() - 2, '}');
}else{
sb1.append(" }");
}
System.out.println("table["+i+"] node is : " + sb1.toString());
}
sb.setCharAt(sb.length() - 1, '}');
return sb.toString();
}
public static void main(String[] args) {
MyHashMap m = new MyHashMap();
Map<Object,Object> hashMap = new HashMap<>();
for(int i=0;i<160;i++){
m.put(i,"data" + i);
//hashMap.put(i,"data" + i);
}
Object deleteKey = -1;
System.out.println("删除元素 key="+deleteKey+", value="+m.remove(deleteKey));
System.out.println(m);
System.out.println("元素个数:" + m.size());
// hashMap.remove(0);
// Iterator it = hashMap.entrySet().iterator();
// while (it.hasNext()) {
// Map.Entry entry = (Map.Entry) it.next();
// int code = entry.hashCode();
// Object key = entry.getKey();
// Object value = entry.getValue();
// System.out.println("code:"+code+"---key:" + key + "---" + "value:" + value);
// }
// System.out.println(hashMap);
}
}