1. Define the class for each entry:
2. maintain an array of entries
3. hash(key) to get the hash#
4. form the hash#, mapped to the entry index.
5. When iterate the corresponding entry for the given key, which is actually a singly linked list, we need compare each of the entry in the list, if the key is the same as the key we want
public static class MyHashMap<String, Integer> {
public static class Entry<String, Integer> {
private final String key;
private int value;
private Entry <String, Integer> next;
public Entry(String key, int value) {
this.key = key;
this.value = value;
}
}
private static final int DEFAULT_CAPACITY = 16;
private static final float DEFAULT_LOAD_FACTOR = 0.75f;
private Entry<String, Integer> [] buckets;
private int capacity;
private float loadFactor;
private int size;
// 用户提供capacity和loadFactor版本
public MyHahsMap(int capacity, float loadFactor) {
this.capacity = capacity;
this.loadFactor = loadFactor;
this.size = 0;
this.buckets = new Entry[capacity];
}
// 用户不提供capacity和loadFactor版本
public MyHahsMap() {
this.capacity = DEFAULT_CAPACITY;
this.loadFactor = DEFAULT_LOAD_FACTOR;
this.size = 0;
this.buckets = new Entry[capacity];
}
//可以告诉我们当前的HashMap里有多少对 Key-Value pair
public int size() {
return this.size;
}
public boolean isEmpty() {
return this.size == 0;
}
private boolean equalsValue(int val1, int val2) {
return val1 == val2;
}
private boolean equalsKey (String key1, String key2) {
return key1.equals(key2);
}
// 给我一个key,给一个不为负数且不超界的hashCode
private int hash(String key) {
if (key == null) {
return 0;
}
return key.hashCode() & 0X7FFFFFFF;
}
//找到key对应的bucket
private int getIndex(String key) {
int hashCode = hash(key);
return hashCode % this.capacity;
//如果当前hashMap里entry/capacity的ratio大于loadFactor,我们就应该rehashing
private boolean needRehashing() {
float ratio = (size + 0.0f) / capacity;
return ratio >= this.loadFactor;
// Arrays.fill 把这个array 填成我们要的值,比如这里将整个hashMap清空,所以Array里全部都是null
private void clear() {
Arrays.fill(this.buckets, null)
size = 0;
}
// 给我一个key,我去找有没有对应值,如果有返回,如果没有就返回null
// 逻辑: 先找到这个key在那个bucket,再对这个bucket里的linkedlist进行遍历,看有没有对应key
public Integer get(String key) {
int index = getIndex(key);
Entry<String, Integer> head = buckets[index];
Entry<String, Integer> cur = head;
while (cur != null) {
if (cur.key.euqals(key)) {
return cur.value;
}
cur = cur.next;
}
return null;
}
// 给我一个key,如果hashMap里有就return true,没有就return false
public boolean containsKey(String key) {
int index = getIndex(key);
Entry<String, Integer> head = buckets[index];
Entry<String, Integer> cur = head;
while (cur != null) {
if (cur.key.equals(key)) {
return true;
}
cur = cur.next;
}
return false;
}
// 逻辑:往map里放入entry <key, value>
// case 1: already exists, update it, return the previous value
// case 2: just insert this entry to the head of linkedList, return null;
// 有可能触发rehashing
public Integer put(String key, Integer value) {
int index = getIndex(key);
Entry<String, Integer> head = buckets[index];
Entry<String, Integer> cur = head;
while (cur != null) {
if (cur.key.equals(key)) {
int result = cur.value;
cur.value = value;
return result;
}
cur = cur.next;
}
// 代码进行到这里说明map里没有对应的entry,我们得把新entry插在head;
Entry<String, Integer> newEntry = new Entry<>(key, value);
newEntry.next = head;
buckets[index] = newEntry;
this.size++;
// check if needRehashing
if (needRehashing()) {
rehashing();
}
return null;
}
// rehasing的逻辑不是抄以前bucket里面的linkedList,
// 而是把以前map里面的每个entry重新计算bucket重新放一遍。
private void rehashing() {
this.capacity = 2;
/*
或者自己定义SCALE_FACTOR
private static final int SCALE_FACTOR = 4;
this.capacity *= SCALE_FACTOR;
*/
Entry<String, Intege>[] newBuckets = new Entry[this.capacity];
//拿出旧buckets里面的所有linkedList的head
for (Entry<String, Integer> eachHead : buckets) {
//遍历每个linkedList的所有Entry
Entry<String, Integer> eachCur = eachHead;
while (eachCur != null) {
Entry<String, Integer> next = eachCur.next;
eachCur.next = null;
// 把eachCur放到新的map里
// 逻辑:算一下index,如果bucket对应index为空,则让它成为头;
// 如果不为空,就把它接在头上,和put()类似
int index = getIndex(eachCur.key);
if (newBuckets[index] == null) {
newBuckets[index] = eachCur;
} else {
eachCur.next = newBuckets[index];
newBuckets[index] = eachCur;
}
eachCur = next;
}
}
this.bucktes = newBuckets;
}
// 逻辑:给我一个key,找到这个map里是否有对应的entry,如果有,就remove,并且返回对应value
// 如果没有,返回null
private Integer remove(String key) {
int index = getIndex(key);
Entry<String, Integer> head = bucktes[index];
Entry<String, Integer> cur = head;
Entry<String, Integer> prev = null;
while (cur != null) {
if (cur.key.equals(key)) {
if (prev == null) {
buckets[index] = cur.next;
} else {
prev.next = cur.next;
}
this.size--;
return cur.value;
}
prev = cur;
cur = cur.next;
}
return null;
}