手写个Hashmap 方便自己理解底层数据结构
hashmap的原理我就不在这里多写了,网上很多很多 所以就直接上代码吧
先写对外的接口,get和put方法
//代码
public interface MyMap<K, V> {
public V put (K k, V v);
public V get (K k);
interface Entry<K, V> {
public K getKey();
public V getValue();
}
}
其中定义了一个内部接口
实现内部接口
class Entry<K, V> implements MyMap.Entry<K, V> {
//其实还有个hash值 但是简易的 就不写了
private K key;
private V value;
private Entry<K, V> next;
public Entry() {
}
public Entry(K key, V value, Entry<K, V> next) {
this.key = key;
this.value = value;
this.next = next;
}
@Override
public K getKey() {
return key;
}
@Override
public V getValue() {
return value;
}
}
实现外部接口 定义一些属性
//数组默认初始长度 使用位移运算符 1左移4位 不懂的去看二进制=。=
private static final int DEFAULT_INITIAL_CAPACITY = 1 << 4;
//阈值比例 默认0.75
private static final float DEFAULT_LOAD_FACTOR = 0.75f;
private int defaultInitSize;
private float defaultLoadFactor;
//map中entry的数量
private int entryUseSize;
//数组
private Entry<K, V>[] table = null;
public MyHashMap(){
this(DEFAULT_INITIAL_CAPACITY, DEFAULT_LOAD_FACTOR);
}
public MyHashMap(int defaultInitialCapacity, float defaultLoadFactor) {
if (defaultInitialCapacity < 0) {
throw new IllegalArgumentException("Illegal initial capacity: " +
defaultInitialCapacity );
}
if (defaultLoadFactor <= 0 || Float.isNaN(defaultLoadFactor)) {
throw new IllegalArgumentException("Illegal load factor: " +
defaultLoadFactor);
}
this.defaultInitSize = defaultInitialCapacity;
this.defaultLoadFactor = defaultLoadFactor;
table = new Entry[this.defaultInitSize];
}
@Override
public V put(K k, V v) {
V oldValue = null;
//是否需要扩容
//扩容完毕 重新散列
if (entryUseSize >= defaultInitSize * defaultLoadFactor) {
resize(2 * defaultInitSize);
}
//得到hash值 计算数组中的位置
int index = hash(k) & (defaultInitSize - 1);
if (table[index] == null) {
table[index] = new Entry<K, V>(k, v, null);
++entryUseSize;
} else { // 遍历单链表
Entry<K, V> entry = table[index];
Entry<K, V> e = entry;
while (e != null) {
if (k == e.getKey() || k.equals(e.getKey())) {
oldValue = e.value;
e.value = v;
return oldValue;
}
e = e.next;
}
table[index] = new Entry<K, V>(k, v, entry);
++entryUseSize;
}
return oldValue;
}
@Override
public V get(K k) {
int index = hash(k) & (defaultInitSize - 1);
if (table[index] == null) {
return null;
} else {
Entry<K, V> entry = table[index];
do {
if (k == entry.getKey() || k.equals(entry.getKey())) {
return entry.getValue();
}
entry = entry.next;
} while (entry != null);
}
return null;
}
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;
entryUseSize = 0;
rehash(newTable);
}
private void rehash(Entry<K, V>[] newTable) {
//得到原来entry集合
List<Entry<K, V>> entryList = new ArrayList<Entry<K, V>>();
for (Entry<K, V> entry : table) {
if (entry != null) {
do {
entryList.add(entry);
entry = entry.next;
} while (entry != null);
}
}
//覆盖旧的引用
if (newTable.length > 0 ) {
table = newTable;
}
//重新put entry
for (Entry<K, V> entry : entryList) {
put(entry.getKey(), entry.getValue());
}
}
class Entry<K, V> implements MyMap.Entry<K, V> {
private K key;
private V value;
private Entry<K, V> next;
public Entry() {
}
public Entry(K key, V value, Entry<K, V> next) {
this.key = key;
this.value = value;
this.next = next;
}
@Override
public K getKey() {
return key;
}
@Override
public V getValue() {
return value;
}
}