package com.example.myhashmap.service;
public interface MyMap {
public V put(K k,V v);
public V get(K k);
interface MyEntry{
public K getKey();
public V getValue();
public void setValue(V value);
MyEntry next();
}
}
自定义一个接口 接口中定义了自定义的Map具备的两个方法 put(),get() 并定义了一个内部接口Entry
实现接口方法中主要定义了几个常量,分别是默认初始化长度 阈值比例
package com.example.myhashmap.service.impl;
import com.example.myhashmap.service.MyMap;
import com.example.myhashmap.service.entry.Entry;
import java.util.ArrayList;
import java.util.List;
public class MyHashMap implements MyMap {
//默认初始化长度
private static final int DEFAULT_INITIAL_CAPACITY = 1 << 4;
//阈值比例
private static final float DEFAULT_LOAD_FACTOR = 0.75f;
//默认大小
private int defaultInitSize;
//阈值比例
private float defaultLoadFactor;
//map中entry的数量
private int entryUserSize;
//数组
private Entry[] table;
public MyHashMap() {
this.defaultInitSize = DEFAULT_INITIAL_CAPACITY;
this.defaultLoadFactor = DEFAULT_LOAD_FACTOR;
table = new Entry[this.defaultInitSize];
}
public MyHashMap(int defaultInitSize, float defaultLoadFactor) throws IllegalAccessException {
if (defaultInitSize <= 0) {
throw new IllegalAccessException("defaultInitSize init error" + defaultInitSize);
}
if (defaultLoadFactor <= 0) {
throw new IllegalAccessException("defaultLoadFactor init error" + defaultLoadFactor);
}
this.defaultInitSize = defaultInitSize;
this.defaultLoadFactor = defaultLoadFactor;
table = new Entry[this.defaultInitSize];
}
@Override
public V put(K k, V v) {
V oldValue = null;
//是否需要扩容 扩容完成是否需要重新散列
if (entryUserSize >= defaultInitSize * defaultLoadFactor) {
resize(2 * defaultInitSize);
}
//得到hash值 计算出数组中的位置
int index = hash(k) & (defaultInitSize - 1);
if (table[index] == null) {
table[index] = new Entry<>(k, v, null);
} else {
//遍历链表
Entry entry = table[index];
Entry e = entry;
while (e != null) {
if (k == e.getKey() || k.equals(e.getKey())) {
oldValue = e.getValue();
e.setValue(v);
return oldValue;
}
e = e.next();
}
table[index] = new Entry<>(k, v, entry);
}
++entryUserSize;
return null;
}
@Override
public V get(K k) {
int index = hash(k) & (defaultInitSize - 1);
if (table[index] == null) {
return null;
} else {
Entry entry = table[index];
do {
if (k == entry.getKey() || k.equals(entry.getKey())) {
return entry.getValue();
}
entry = entry.next();
} while (entry != null);
}
return null;
}
//取hash值
private int hash(K k) {
int hashCode = k.hashCode();
hashCode ^= (hashCode >>> 20) ^ (hashCode >>> 12);
return hashCode ^ (hashCode >>> 7) ^ (hashCode >>> 4);
}
//扩容
private void resize(int i) {
Entry[] newTable = new Entry[i];
defaultInitSize = i;
entryUserSize = 0;
rehash(newTable);
}
private void rehash(Entry[] newTable) {
//得到原来老的集合 遍历单链表
List> entryList = new ArrayList<>();
for (Entry entry : this.table) {
if (entry != null) {
do {
entryList.add(entry);
entry = entry.next();
} while (entry != null);
}
}
//覆盖旧的引用
if (newTable.length > 0) {
this.table = newTable;
}
//重新put entry 到 hashMap
for (Entry entry : entryList) {
put(entry.getKey(), entry.getValue());
}
}
}
定义了map的数据结构 其中next为发生hash冲突时使用单链表进行存储
package com.example.myhashmap.service.entry;
import com.example.myhashmap.service.MyMap;
public class Entry implements MyMap.MyEntry {
private K key;
private V value;
private Entry next;
public Entry(K key,V value,Entry next){
this.key = key;
this.value =value;
this.next = next;
}
@Override
public Entry next(){
return this.next;
}
@Override
public K getKey() {
return key;
}
@Override
public V getValue() {
return value;
}
@Override
public void setValue(V value) {
this.value = value;
}
}
public V put(K k, V v) {
V oldValue = null;
//是否需要扩容 扩容完成是否需要重新散列
if (entryUserSize >= defaultInitSize * defaultLoadFactor) {
resize(2 * defaultInitSize);
}
//得到hash值 计算出数组中的位置
int index = hash(k) & (defaultInitSize - 1);
if (table[index] == null) {
table[index] = new Entry<>(k, v, null);
} else {
//遍历链表
Entry entry = table[index];
Entry e = entry;
while (e != null) {
if (k == e.getKey() || k.equals(e.getKey())) {
oldValue = e.getValue();
e.setValue(v);
return oldValue;
}
e = e.next();
}
table[index] = new Entry<>(k, v, entry);
}
++entryUserSize;
return null;
}
//取hash值
private int hash(K k) {
int hashCode = k.hashCode();
hashCode ^= (hashCode >>> 20) ^ (hashCode >>> 12);
return hashCode ^ (hashCode >>> 7) ^ (hashCode >>> 4);
}
//扩容
private void resize(int i) {
Entry[] newTable = new Entry[i];
defaultInitSize = i;
entryUserSize = 0;
rehash(newTable);
}
private void rehash(Entry[] newTable) {
//得到原来老的集合 遍历单链表
List> entryList = new ArrayList<>();
for (Entry entry : this.table) {
if (entry != null) {
do {
entryList.add(entry);
entry = entry.next();
} while (entry != null);
}
}
//覆盖旧的引用
if (newTable.length > 0) {
this.table = newTable;
}
//重新put entry 到 hashMap
for (Entry entry : entryList) {
put(entry.getKey(), entry.getValue());
}
}
@Override
public V get(K k) {
//获取hash值 与put 中的计算方法一致
int index = hash(k) & (defaultInitSize - 1);
//直接获取数组中的指定位置的值
if (table[index] == null) {
return null;
} else {
//如果指定位置为链表的话 继续遍历
Entry entry = table[index];
do {
if (k == entry.getKey() || k.equals(entry.getKey())) {
return entry.getValue();
}
entry = entry.next();
} while (entry != null);
}
return null;
}
package com.example.myhashmap.service.test;
import com.example.myhashmap.service.impl.MyHashMap;
public class Test {
public static void main(String[] args) {
MyHashMap myMap = new MyHashMap<>();
for (int i = 0; i < 500; i++) {
myMap.put("key"+i,"value"+i);
}
for (int i = 0; i <500 ; i++) {
System.out.println(myMap.get("key"+i));
}
}
}