1.首先根据数组和链表表示1.8之前的hashmap(1.7)
hashmap其实就是一个数组,每个数值对应一个单向链表
1.实现基本类,创建结构的组成元素
继承map.entry<k,v>在这个类中有四种变量,k,v,hash,next,写构造函数,重写get,set方法
static class HashMapEntry<K,V> implements Map.Entry<K,V>{
public K key;
public V value;
public int hash;//数组下标
public HashMapEntry next;//指针:指向链表下一元素
//开始构造函数
public HashMapEntry(K key, V value, int hash, HashMapEntry next){
this.key = key;
this.value = value;
this.hash = hash;
this.next = next;
}
@Override
public K getKey() {
return key;
}
@Override
public V getValue() {
return value;
}
@Override
public V setValue(V value) {
V oldValue = this.value;
this.value = value;
return oldValue;
}
@Override
public int hashCode(){
return ((key == null)?0:key.hashCode())^((value == null)? 0: value.hashCode());
}
@Override
public String toString(){
return "HashMapEntry{"+
"key = "+key+
", value = "+ value +
", hash = "+ hash +
", next = " + next +
"}";
}
}
2.开始定义变量,写put,get,remove方法
2.1定义常量,变量,集合元素
private static final int min_capacity = 4;//100,最小容量
private static final int max_capacity = 1<<30; //将上面的二进制数字向左移动30位后面补0得到 0100 0000 0000 0000 0000 0000 0000 0000,最高位是符号位,(length-1)&hash确认位置
//按二进制形式把所有的数字向右移动对应位数,低位移出(舍弃),高位的空位补符号位,即正数补零,负数补1,最大容量
private static final Map.Entry[] empty_table = new HashMapEntry[min_capacity>>1];//两个字节2,10,空map初始化
private int size;//元素个数
private int threshold;//扩容临界值
private HashMapEntry<K,V>[] table;//类中公共数组
private HashMapEntry<K,V> entryForNullKey;//key为null的元素
2.2定义和重载构造方法
public HashMap1(){//无参构造函数
table = (HashMapEntry<K, V>[]) empty_table;
threshold = -1;
}
public HashMap1(int capacity){//有参构造函数
if (capacity < 0){
throw new IllegalArgumentException("Capacity:"+capacity);
}
if (capacity == 0) {
HashMapEntry<K,V>[] emptytab = (HashMapEntry<K, V>[]) empty_table;
table = emptytab;
threshold = -1;
return;
}
if (capacity < min_capacity){
capacity = min_capacity;
}else if (capacity > max_capacity){
capacity = max_capacity;
}else {
capacity = roundUpToPowerOfTwo(capacity);//取大于且最接近capacity的2的幂
}
makeTable(capacity);
}
private HashMapEntry<K,V>[] makeTable(int capacity) {//根据容量构造hashmap
HashMapEntry<K,V>[] newTable = new HashMapEntry[capacity];
table = newTable;
threshold = (capacity>>1) + (capacity>>2);//0.75
return newTable;
}
private int roundUpToPowerOfTwo(int capacity) {//取大于且最接近capacity的2的幂
return capacity;
}
2.3定义get方法
public V get(Object key){//取数据
if (key == null){
HashMapEntry<K,V> entry = this.entryForNullKey;
return entry==null?null:entry.getValue();
}
int hash = secondaryHash(key.hashCode());
HashMapEntry<K,V>[] tab = table;
int index = hash & (tab.length - 1);
HashMapEntry<K,V> entry = tab[index];
for (HashMapEntry<K,V> e = entry;e!=null;e = e.next){
if (key == e.key || (hash == e.hash && key.equals(e.key))){
// if (e.hash == hash && (e.key == key || key.equals(e.key)))
return e.getValue();
}
}
return null;
}
private int secondaryHash(int hashCode) {
return hashCode;
}
2.4 定义remove方法
public V remove(Object key){//删除数据
if (key == null){
return removeNullKey();
}
int hash = secondaryHash(key.hashCode());
HashMapEntry<K,V>[] tab = table;
int index = hash & (tab.length - 1);
HashMapEntry<K,V> entry = tab[index];
//使用双指针移除元素
for( HashMapEntry<K,V> e = entry,prev = null;e!= null;prev = e,e = e.next){
if (hash == e.hash && key.equals(e.key)){
if (prev == null){//表示第一个就是
tab[index] = e.next;
}else {//不是第一个,将其移除
prev.next = e.next;
}
size--;
return e.getValue();
}
}
return null;
}
private V removeNullKey() {
HashMapEntry<K,V> e = entryForNullKey;
if (e == null){
return null;
}
entryForNullKey = null;
size--;
return e.value;
}
2.5put方法
public V put(K key, V value){
if (key == null){
return putValueForNullKey(value);
}
HashMapEntry<K,V>[] tab = table;
int hash = secondaryHash(key.hashCode());
int index = hash & (tab.length - 1);
for (HashMapEntry<K,V> entry = tab[index];entry!= null;entry = entry.next){
if (entry.hash == hash && key.equals(entry.key)){
return entry.setValue(value);
}
}
if (size++ > threshold){
tab = doubleCapacity();
index = hash & (tab.length - 1);
}
addNewEntry(key,value,hash,index);
return null;
}
public int size(){
return size;
}
private void addNewEntry(K key, V value, int hash, int index) {//链表添加新节点
table[index] = new HashMapEntry<>(key,value,hash,table[index]);
}
private HashMapEntry<K,V>[] doubleCapacity() {//扩容算法
HashMapEntry<K,V>[] oldTable = table;
int oldCapacity = oldTable.length;
if (oldCapacity == max_capacity){
return oldTable;
}
int newCapacity = oldCapacity * 2;
HashMapEntry<K,V>[] newTable = makeTable(newCapacity);
if (size == 0){
return newTable;
}
return null;
}
1.8之后
getNode方法如下,多了一个红黑树的查找
final Node<K,V> getNode(int hash, Object key) {
Node<K,V>[] tab; Node<K,V> first, e; int n; K k;
//当table已经初始化,长度大于0,且根据hash查询位置也不为空
if ((tab = table) != null && (n = tab.length) > 0 &&(first = tab[(n - 1) & hash]) != null) {
if (first.hash == hash && // always check first node若第一项的key和hash相同,则直接返回第一项
((k = first.key) == key || (key != null && key.equals(k))))
return first;
if ((e = first.next) != null) {//若不是第一项且后面还有值
if (first instanceof TreeNode)//若为红黑树,再红黑树中查找
return ((TreeNode<K,V>)first).getTreeNode(hash, key);
do {//否则在链表中查找
if (e.hash == hash &&((k = e.key) == key || (key != null && key.equals(k))))
return e;
} while ((e = e.next) != null);
}
}
return null;//都没找到就返回空
}