HashMap数据结构——数组+链表
Node[]是HashMap的核心数组结构,也称之为“位桶数组“,长度默认是16
Node的源码:
/**
* Basic hash bin node, used for most entries. (See below for
* TreeNode subclass, and in LinkedHashMap for its Entry subclass.)
*/
static class Node<K,V> implements Map.Entry<K,V> {
final int hash;
final K key;
V value;
Node<K,V> next;
Node(int hash, K key, V value, Node<K,V> next) {
this.hash = hash;
this.key = key;
this.value = value;
this.next = next;
}
public final K getKey() { return key; }
public final V getValue() { return value; }
public final String toString() { return key + "=" + value; }
public final int hashCode() {
return Objects.hashCode(key) ^ Objects.hashCode(value);
}
public final V setValue(V newValue) {
V oldValue = value;
value = newValue;
return oldValue;
}
public final boolean equals(Object o) {
if (o == this)
return true;
if (o instanceof Map.Entry) {
Map.Entry<?,?> e = (Map.Entry<?,?>)o;
if (Objects.equals(key, e.getKey()) &&
Objects.equals(value, e.getValue()))
return true;
}
return false;
}
}
存储数据过程put(key,value)
- hashcode是一个整数,需要将它转化成[0,数组长度-1]的范围。要求转换后的值尽量均匀分布在[0,数组长度-1]这个区间,减少"hash冲突"。
- 散列算法:均匀分布,充分利用数组的寻址快的特点
常见算法:相除取余——hash=hashcode%数组长度,这种算法可以让hash值均匀的分布在[0,数组长度-1]的区间。早期的HashTable就是采用的这种算法。但是这种算法由于使用了“除法”,效率低下。后来JDK改进了算法,首先约定数组的长度必须是2的整数幂,这样采用位运算即可实现取余的效果:hash=hashcode&(数组长度-1)
package cn.GTMStudion.collection;
public class TestMyHash {
public static void main(String[] args) {
int h=98989778;
int length=16;
myHash(h,length);
}
/**
*
* @param h 任意整数
* @param length 长度必须为2的整数次幂,则h&(length-1)相当于对length取模
* @return
*/
public static int myHash(int h,int length){
System.out.println(h&length-1);
//length为2的整数幂情况下,和取余的值一样
System.out.println(h%length);//取余数
return h&(length-1);
}
}