今天没有研究技术,所以想着仿写一遍简单的hashmap源码,仅供参考,实现方法有很多
我采用的尾插发,并实现了自动扩容,红黑树太复杂了,你可以看成是jdk1.7的简化hashmap
,实现了指定table长度构造,put ,contains,扩容,get
import java.util.Arrays;
import java.util.HashMap;
/**
* \* Created with IntelliJ IDEA.
* \* @author: zth
* \* Date: 2022/3/31
* \* Time: 16:06
* \* To change this template use File | Settings | File Templates.
* \* Description: 仿写hasmap源码
* \
*/
public class ZHashMap<K,V>{
private Node<K,V>[] table = null;//table数组
static private int LENGTH = 16;//记录table长度
static private int SIZE = 0;//记录元素数量
final static float FACTOR = 0.75f;//负载因子
public ZHashMap() {
}
public ZHashMap(int LENGTH) {//指定table长度
this.LENGTH=tableSizeFor(LENGTH);
}
//处理输入的数据让其自动变成2的次方
static final int tableSizeFor(int cap) {
int n = cap - 1;
n |= n >>> 1;
n |= n >>> 2;
n |= n >>> 4;
n |= n >>> 8;
n |= n >>> 16;
return (n < 0) ? 1 : (n >= Integer.MAX_VALUE) ? Integer.MAX_VALUE : n + 1;
}
public V get(K key){
Node<K,V> n = table[hashForCode(key.hashCode())];
while (n!=null){
if(n.hashkey==key.hashCode()&&key==n.Key)return n.value;
n=n.next;
}
return null;
}
public void remove(K key){
Node<K,V> n = table[hashForCode(key.hashCode())];
if(n!=null&&n.hashkey==key.hashCode()&&key==n.Key){//如果第一个就是
table[hashForCode(key.hashCode())]=n.next;
}else{
Node t =null;//记录上一层指针
while (n!=null){
if(n.hashkey==key.hashCode()&&key==n.Key){
t.next=n.next;
}
t=n;
n=n.next;
}
}
}
public boolean contains(V value){
for (Node n:table
) {
Node t =n;
while (t!=null){
if(n.value==value)return true;
t=t.next;
}
}
return false;
}
public void put(K key , V value){
resize();
if(putVal(key.hashCode(),key,value))SIZE++;//调用putVal,只有当添加成功时数量加一,覆盖不变
}
private boolean putVal(int hasdcode,K key , V value){
Node<K,V> n = table[hashForCode(hasdcode)];
if(n==null){
table[hashForCode(hasdcode)]=new Node<K,V>(key,hasdcode,value);
return true;
}
else {
Node<K,V> t = null;
while (n!=null){
t=n;//记录这个节点
if(hasdcode==n.hashkey&&key==n.Key){//重复进行覆盖
n.value=value;
return false;//覆盖返回false
}
n=n.next;
}
if(t!=null){
t.next=new Node<K,V>(key,hasdcode,value);//连接新节点
return true;
}else return false;
}
}
public void resize(){
Node<K,V>[] oldta = table;//记录原数组
if(table==null){
table = (Node<K,V>[])new Node[LENGTH];
System.out.println("初始扩容");
System.out.println(table.length);
}
if(SIZE>=LENGTH*FACTOR&&table!=null){
System.out.println("执行扩容");
LENGTH=LENGTH*2;
table=(Node<K,V>[]) new Node[LENGTH];//建立新的table数组
for (Node n:oldta
) {
if(n!=null){
//遍历所有节点添加
Node<K,V> temp = n;
while(temp!=null){
putVal(temp.hashkey,temp.Key,temp.value);//重新添加
temp=temp.next;
}
}
}
System.out.println(table.length);
}
}
static final int hashForCode(int hash){
return hash%LENGTH;
}
/*
*
* @author: zth
* @Description:
* @method: 节点处理
* @date: 2022/4/4 12:55
* @param:
* @return:
*
*/
static class Node<K,V>{
final K Key;
final int hashkey;
private V value;
Node<K,V> next;
public Node(K key, int hashkey, V value) {
Key = key;
this.hashkey = hashkey;
this.value = value;
}
@Override
public String toString() {
return "Node{" +
"Key=" + Key +
", value=" + value +
", next=" + next +
'}';
}
}
@Override
public String toString() {
for (int i = 0; i < table.length; i++) {
System.out.println("索引位"+i+" "+table[i]);
}
return "";
}
}
main方法测试相关功能
import java.util.HashMap;
/**
* \* Created with IntelliJ IDEA.
* \* @author: zth
* \* Date: 2022/3/31
* \* Time: 16:11
* \* To change this template use File | Settings | File Templates.
* \* Description:
* \
*/
public class Main {
public static void main(String[] args) {
ZHashMap<String , Integer> zHashMap = new ZHashMap<>(12);//测试构造时输入非2的次方的数
System.out.println("测试所有方法");
for (int i = 0; i < 11; i++) {//正常添加
zHashMap.put("key"+i,i);
}
zHashMap.put("重地",7788);//扩容
zHashMap.put("通话",9917);//存储hashcode相同的key,进行拉链
System.out.println(zHashMap.get("重地"));//测试get()方法
System.out.println(zHashMap.get("哈哈"));//测试get()方法
System.out.println(zHashMap.contains(7788));//测试contains()方法
System.out.println(zHashMap.contains(7766));//测试contains()方法
System.out.println(zHashMap.toString());
zHashMap.remove("重地");//测试remove()方法
zHashMap.remove("哈哈");//测试remove()方法,移除不存在的key
System.out.println(zHashMap.toString());
}
}
如有BUG请见谅,菜菜不易