手寫HashMap,帶註解
阿新 • • 發佈:2020-12-08
技術標籤:java
程式碼不全,覺得重要的就寫下去,直接執行是執行不了的,主要是我後面懶了。。。
但是大概思路還是有的
等不懶的時候再補補
import javax.xml.soap.Node;
import java.io.Serializable;
import java.util.*;
/**
* @author chy
* @create 2020-12-04-15:45
*/
public class MyHashMap<K,V> extends AbstractMap<K,V>
implements Map<K,V>, Cloneable, Serializable {
/** 預設大小*/
private int DEFAULT_SIZE = 1 << 4;
/** 最大值*/
private int MAX_SIZE = 1 << 30;
/** 擴容因子*/
private float DEFAULT_LOAD_FACTOR = 0.75f;
/** 含量大小*/
private int size;
/** 實際的擴容因子 */
private float loadFactor;
/** 實際大小*/
private int threshold;
transient int modCount;
/**
* 存放節點的陣列
*/
transient MyNode<K,V>[] table;
/**
* 計算hash值
* @param key
* @return
*/
static final int hash(Object key) {
int h;
return (key == null) ? 0 : (h = key.hashCode()) ^ (h >>> 16);
}
/**
* 建構函式
* @param initSize 初始化大小
* @param loadFactor 擴容因子
*/
public MyHashMap(int initSize, float loadFactor) throws Exception {
if (initSize < 0){
throw new Exception("大小不能為負數");
}
if (0 >=loadFactor){
throw new Exception("大小不能為0");
}
if (1 <loadFactor){
throw new Exception("大小不能大於1");
}
if (initSize > this.MAX_SIZE){
initSize = this.MAX_SIZE;
}
this.threshold = tableSizeFor(initSize);
this.loadFactor = loadFactor;
}
/**
*
*/
public MyHashMap(){
this.loadFactor = DEFAULT_LOAD_FACTOR;
}
/**
* 獲取大於等於 目標值的最小的2的冪,便於hash計算
* @param size
* @return
*/
public int tableSizeFor(int size){
int n = size -1;
n |= n>>>1;
n |= n>>>2;
n |= n>>>4;
n |= n>>>8;
//最大隻有30位,右移16夠了
n |= n>>>16;
return n<0? 1 : n >= MAX_SIZE ? MAX_SIZE : n+1;
}
/**
* 根據key跟hash獲取節點
* @param hash
* @param key
* @return
*/
final MyNode<K,V> getNode(int hash, Object key) {
MyNode<K,V>[] tab; MyNode<K,V> first, e; int n; K k;
//判斷table是否初始化
if ((tab = table) != null && (n = tab.length) > 0 &&
//獲取頭節點
(first = tab[(n - 1) & hash]) != null) {
//頭節點是否是目標值
if (first.hash == hash &&
((k = first.key) == key || (key != null && key.equals(k)))) {
return first;
}
//遍歷節點佇列
if ((e = first.next) != null) {
do {
if (e.hash == hash &&
((k = e.key) == key || (key != null && key.equals(k)))) {
return e;
}
} while ((e = e.next) != null);
}
}
return null;
}
/**
* 獲取value,當節點不存在返回defualtValue
* @param key
* @param defaultValue
* @return
*/
@Override
public V getOrDefault(Object key, V defaultValue) {
MyNode<K,V> e;
return (e = getNode(hash(key), key)) == null ? defaultValue : e.value;
}
@Override
public int size() {
return size;
}
@Override
public boolean isEmpty() {
return size > 0;
}
@Override
public boolean containsKey(Object key) {
return getNode(hash(key),key) != null;
}
@Override
public boolean containsValue(Object value) {
MyNode<K,V>[] table = this.table;
V v;
// 判斷table是否為空
if (table!=null && size >0){
//遍歷table
for (int i = 0; i < table.length; ++i) {
//遍歷MyNode 列表
for (MyNode<K,V> n = table[i]; n != null; n = n.next){
if ((v = n.value) == value ||
(value != null && value.equals(v))){
return true;
}
}
}
}
return false;
}
@Override
public V get(Object key) {
MyNode<K,V> node;
return (node = getNode(hash(key),key)) == null? null : node.value;
}
@Override
public V put(K key, V value) {
return putVal(hash(key),key,value);
}
/**
*
* @param hash
* @param key
* @param value
* @return
*/
final V putVal(int hash, K key, V value){
MyNode<K,V>[] tab; MyNode<K,V> p; int n, i;
// 如果table沒有初始化,則為table初始化
if ((tab = table) == null || (n = tab.length) == 0) {
n = (tab = resize()).length;
}
//hash不存在,則新加入節點到對應hash
if ((p = tab[i = (n - 1) & hash]) == null) {
tab[i] = new MyNode(hash, key, value, null);
} else {
MyNode<K,V> e; K k;
//key已經存在
if (p.hash == hash &&
((k = p.key) == key || (key != null && key.equals(k)))) {
e = p;
//hash 相等,key不等
} else {
for (int binCount = 0; ; ++binCount) {
if ((e = p.next) == null) {
p.next = new MyNode(hash, key, value, null);
//如果大於 8(可更改),則轉換為紅黑樹
// if (binCount >= TREEIFY_THRESHOLD - 1){
// treeifyBin(tab, hash);
// }
// break;
}
if (e.hash == hash &&
((k = e.key) == key || (key != null && key.equals(k)))) {
break;
}
p = e;
}
}
if (e != null) {
V oldValue = e.value;
if ( oldValue == null) {
e.value = value;
}
return oldValue;
}
}
++modCount;
if (++size > threshold) {
resize();
}
return null;
}
@Override
public V remove(Object key) {
return null;
}
@Override
public void putAll(Map<? extends K, ? extends V> m) {
}
@Override
public void clear() {
}
@Override
public Set<K> keySet() {
Set<Map.Entry<K,V>> es;
return (es = entrySet) == null ? (entrySet = new HashMap.EntrySet()) : es;
}
@Override
public Collection<V> values() {
return null;
}
@Override
public Set<Map.Entry<K, V>> entrySet() {
return null;
}
@Override
public boolean equals(Object o) {
return false;
}
@Override
public int hashCode() {
return 0;
}
class MyNode<K,V> implements Map.Entry<K,V>{
final int hash;
final K key;
V value;
MyNode<K,V> next;
MyNode(int hash, K key, V value, MyNode<K,V> next) {
this.hash = hash;
this.key = key;
this.value = value;
this.next = next;
}
@Override
public K getKey() {
return key;
}
@Override
public V getValue() {
return value;
}
@Override
public V setValue(V value) {
this.value = value;
return this.value;
}
}
public static void main(String[] args) {
MyHashMap myHashMap = new MyHashMap();
System.err.println(myHashMap.DEFAULT_SIZE +" "+myHashMap.MAX_SIZE);
}
}