前言
为了加深对于HashMap的理解,可以手写HashMap理解底层操作原理
我们知道HashMap在jdk1.8之后使用了数组 + 链表 + 红黑树的结构,那么在自己实现HashMap的时候需要注意这一点;我将手动实现HashMap的节点、get()、put()方法
1.get()方法的流程
- 通过 key 进行hash运算,得到 index
- 判断 index 是否为空,为空则返回 null
- 不为空,则判断传入的当前节点是否有 next ,为链表还是红黑树,遍历链表或红黑树返回值
2.put()方法的流程
- 求出 key 的哈希值,得到 index,并得到 index 对应的对象
- 如果 index 的对象为空,则直接赋值
- 如果当前 index 的对象不为空,则使用链表存储
3.手写Map接口
先自定义一个Map接口
public interface MyMap<K, V>{
int size();
V put(K k, V v);
V get(K k);
V remove(K k);
interface Entry(K, V){
K getKey();
V getValue();
}
}
自定义一个Entry
class Entry<K, V> implements MyMap.Entry<K, V>{
int hash;
K k;
V v;
Entry<K, V> next;
public ENtry(K k, V v, Entry<K, V> next, int hash){
this.k = k;
this.v = v;
this.hash = hash;
this.next = next;
}
public K getKey(){
return k;
}
public V getValue(){
return v;
}
}
4.自定义put()、get()、remove()方法
public class MyHashMap<K, V> implements MyMap<K, V>{
Entry[] table = null;
int size = 0;
public MyHashMap(){
table = new Entry[16];
}
public int size(){
return size;
}
//自定义的put()
public V put(K k, V v){
//该key的索引:存储在entry数组中的位置
int index = hash(k);
//该key的哈希值
int hash = k.hashCode();
Entry<K, V> entry = table[index];
if(entry == null){
table[index] = new Entry<>(k, v, null, hash);
size++;
}else{
table[index] = new Entry<>(k, v, entry, hash);
}
return (V)table[index].getValue();
}
private int hash(K k){
int index = k.hashCode() % (table.length - 1);
if(index < 0){
return -index;
}
return index;
}
//自定义get()方法
public V get(K k){
int index = hash(K);
int hash = k.hashCode();
Entry<K, V> entry = table[index];
if(entry == null){
return null;
}else{
//不为空,则比较输入的key 和 存在于哈希表中的key相比较;相同则返回数据
if(entry.getKey() == k && hash = entry.hash){
return entry.getValue();
}
//遍历节点,找到相同的值
Entry<K, V> next = entry.next;
while(null != next){
if(entry.getKey() == k && hash = entry.hash){
return entry.getValue();
}
next = next.next;
}
}
return null;
}
//自定义remove()方法
public V remove(K k){
int index = hash(K);
int hash = k.hashCode();
Entry<K, V> entry = table[index];
if(entry == null){
return null;
}else{
if(entry.getKey() == k && entry.hash = hash){
entry = entry.next;
table[index] = entry;
return (V)table[index];
}
if(null != entry.next){
Entry<K, V> head = entry;
Entry<K, V> p = head;
Entry<K, V next = head.next;
do{
if(next.getKey() == k && next.hash == has){
p.next = next.next;
break;
}
p = next;
next = next.next;
}while(next != null);
}else{
table[index] = null;
}
return table[index] == null ? null : (V)table[index].getValue();
}
}