package base.base;
import java.io.Serializable;
import java.util.*;
/**
* @author liu
* Created 2018 - 11 - 08 - TIME
*/
public class MyHashMap<K, V> implements Serializable {
// 1.HashMap: 众所周知,HashMap是一个key-value键值对集合,每一个键值对抽象为Entry(Node),这个数组就是HashMap的主干。
// 2.HashMap数据结构: 哈希表(数组 + 链表)。
// 接下来,我们就以HashMap的常见操作为例,来驱动我们的理解。
// 默认容量
static int DEFAULT_INITIAL_CAPACITY = 16;
// 最大容量
static final int MAXIMUM_CAPACITY = 1 << 30;
// 默认加载因子
static float DEFAULT_LOAD_FACTOR = 0.75f;
// 当前容器大小
private int capacity;
// 存储数据的table
transient Node<K, V>[] table;
// HashMap的大小
transient int size;
// 当前HashMap的修改次数
transient int modCount;
// 加载因子,也可以称为扩容因子
float loadFactor;
// HashMap 键集合
transient Set<K> keySet;
// HashMap values集合
transient Collection<V> values;
public MyHashMap() {
this(DEFAULT_INITIAL_CAPACITY);
this.loadFactor = DEFAULT_LOAD_FACTOR; // all other fields defaulted
}
public MyHashMap(int capacity) {
if (capacity < 0) {
throw new RuntimeException();
} else {
this.table = new Node[capacity];
this.capacity = capacity;
this.size = 0;
}
}
// HashMap节点
static class Node<K, V> {
int hash = 0;
K key = null;
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;
}
@Override
public final String toString() {
return key + "=" + value;
}
@Override
public final int hashCode() {
return Objects.hashCode(key) ^ Objects.hashCode(value);
}
public final V setValue(V newValue) {
V oldValue = value;
value = newValue;
return oldValue;
}
@Override
public final boolean equals(Object o) {
if (o == this) {
return true;
}
if (o instanceof Node) {
Node<?, ?> e = (Node<?, ?>) o;
if (Objects.equals(key, e.getKey()) &&
Objects.equals(value, e.getValue()))
return true;
}
return false;
}
}
final int hash(K key) {
// int h;
// return (key == null) ? 0 : (h = key.hashCode()) ^ (h >>> 16);
// double tmp = key.hashCode() * (Math.pow(5, 0.5) - 1) / 2;
// double digit = tmp - Math.floor(tmp);
// return (int) Math.floor(digit * capacity);
return key.hashCode() & (capacity - 1);
}
public int size() {
return size;
}
public boolean isEmpty() {
return size == 0;
}
public V get(K key) {
Node<K, V> e;
return (e = getNode(hash(key), key)) == null ? null : e.value;
}
private Node<K, V> getNode(int hash, K key) {
Node<K, V>[] tab = table;
Node<K, V> p;
p = tab[hash];
while (p != null) {
if (p.getKey().equals(key)) {
return p;
}
p = p.next;
}
return null;
}
public V put(K key, V value) {
return putVal(hash(key), key, value, false, true);
}
private V putVal(int hash, K key, V value, boolean onlyIfAbsent, boolean evict) {
Node<K, V>[] tab = table;
Node<K, V> p;
Node<K, V> newNode = new Node<K, V>(hash, key, value, null);
p = tab[hash];
while (p != null) {
if (p.getKey().equals(key)) {
p.value = value;
return value;
}
p = p.next;
}
newNode.next = tab[hash];
tab[hash] = newNode;
size++;
return value;
}
public V remove(K key) {
Node<K, V> e;
return (e = removeNode(hash(key), key)) == null ?
null : e.value;
}
public boolean containsKey(K key) {
return getNode(hash(key), key) != null;
}
private Node<K, V> removeNode(int hash, K key) {
Node<K, V>[] tab = table;
Node<K, V> p = tab[hash];
// If the node is head node
if (p.getKey().equals(key)) {
tab[hash] = p.next;
size--;
return p;
} else {
while (p.next != null) {
if (p.next.getKey().equals(key)) {
if (p.next.next == null) {
p.next = null;
size--;
return p.next;
}
p.next = p.next.next;
p.next = null; //GC
size--;
return p.next;
}
p = p.next;
}
}
return null;
}
public Set<K> keySet() {
Set<K> ks = keySet;
if (ks == null) {
ks = new KeySet();
keySet = ks;
}
return ks;
}
abstract class HashIterator {
Node<K, V> next;
Node<K, V> current;
int expectedModCount;
int index;
HashIterator() {
expectedModCount = modCount;
Node<K, V>[] t = table;
current = next = null;
index = 0;
if (t != null && size > 0 && index < t.length) {
next = t[index++];
}
}
public final boolean hasNext() {
return next != null;
}
final Node<K, V> nextNode() {
Node<K, V>[] t;
Node<K, V> e = next;
if (modCount != expectedModCount)
throw new ConcurrentModificationException();
if (e == null)
throw new NoSuchElementException();
if ((next = (current = e).next) == null && (t = table) != null) {
do {
} while (index < t.length && (next = t[index++]) == null);
}
return e;
}
public final void remove() {
Node<K, V> p = current;
if (p == null)
throw new IllegalStateException();
if (modCount != expectedModCount)
throw new ConcurrentModificationException();
current = null;
K key = p.key;
removeNode(hash(key), key);
expectedModCount = modCount;
}
}
final class KeyIterator extends HashIterator implements Iterator<K> {
public final K next() {
return nextNode().key;
}
}
final class KeySet<K> extends AbstractSet<K> {
@Override
public Iterator<K> iterator() {
return (Iterator<K>) new KeyIterator();
}
public final int size() {
return size;
}
}
}