package cn.test; import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.Set; /** * @Description : 手寫HashMap的實現 * @Author : houshuiqiang@163.com, 2016年6月10日 下午2:06:22 * @Modified :houshuiqiang@163.com, 2017年6月11日 */ public class MyHashMap<K, V> implements Map<K, V> { private int modCount; private Node<K, V>[] table; private int size; private int capacity; private static final int DEFAULT_CAPACITY = 16; private static final int MAX_CAPACITY = 2^16; private float loadFactor; private static final float DEFAULT_LOAD_FACTOR = 0.75F; private static final int INCREMENT_FACTOR = 2; private int capacitySize; // 當前set最多容許存放多少個元素,超過則須要擴容 public MyHashMap() { this(DEFAULT_CAPACITY); } public MyHashMap(int capacity) { this(capacity, DEFAULT_LOAD_FACTOR); } @SuppressWarnings("unchecked") public MyHashMap(int capacity, float loadFactor) { vertifyConsturctorCapacity(capacity); vertiryConsturctorLoadFactor(loadFactor); table = new Node[this.capacity]; capacitySize =(int) (this.capacity * this.loadFactor); } @Override public int size() { return size; } @Override public boolean isEmpty() { return size == 0; } @Override public boolean containsKey(Object key) { return keySet().contains(key); } @Override public boolean containsValue(Object value) { for (int i = 0; i < table.length; i++) { Node<K, V> node = table[i]; if (node == null) { continue; }else{ while(node != null) { if (value == null && node.v == null || node.v != null && node.v.equals(value)) { return true; } node = node.nextNode; } } } return false; } @Override public V get(Object key) { for (int i = 0; i < table.length; i++) { Node<K, V> node = table[i]; if (node == null) { continue; }else{ while(node != null) { if (key == null && node.k == null || key != null && node.k != null && node.k.hashCode() == key.hashCode() && node.k.equals(key)) { return node.v; } node = node.nextNode; } } } return null; } @Override public V put(K key, V value) { ifIncrement(); if (null == key) { Node<K, V> node = table[0]; boolean alreadyHasNull = false; while(node != null && !alreadyHasNull) { alreadyHasNull = node.k == null; node = node.nextNode; } if (!alreadyHasNull) { table[0] = new Node<K, V>(key, value, 0, table[0]); size++; modCount++; } return null; } int hash = hash(key.hashCode()); int index = indexOfTable(hash); Node<K, V> node = table[index]; boolean alreadyHas = false; V returnValue = null; while (node != null && !alreadyHas) { alreadyHas = node.k != null && hash == node.hash && key.equals(node.k); if(alreadyHas){ returnValue = node.v; node.v = value; } node = node.nextNode; } if (!alreadyHas) { table[index] = new Node<K, V>(key, value, hash, table[index]); size++; modCount++; } return returnValue; } @Override public V remove(Object key) { Node<K, V> node = removeKey(key); return node == null ? null : node.v; } @SuppressWarnings({ "rawtypes", "unchecked" }) @Override public void putAll(Map<? extends K, ? extends V> m) { Set<?> entrySet = m.entrySet(); for (Object object : entrySet) { if (object instanceof java.util.Map.Entry) { java.util.Map.Entry entry = (java.util.Map.Entry)object; this.put((K)entry.getKey(), (V)entry.getValue()); } } } @Override public void clear() { Arrays.fill(table, null); size = 0; modCount++; } @Override public Set<K> keySet() { return new KeySet(); } @Override public Collection<V> values() { List<V> arrayList = new ArrayList<V>(); Iterator<java.util.Map.Entry<K, V>> iterator = entrySet().iterator(); while(iterator.hasNext()){ arrayList.add(iterator.next().getValue()); } return arrayList; } @Override public Set<java.util.Map.Entry<K, V>> entrySet() { return new EntrySet(); } private void vertifyConsturctorCapacity(int capacity){ if (capacity < 0) { throw new IllegalArgumentException("初始容量不合法"); } if (capacity > MAX_CAPACITY) { this.capacity = MAX_CAPACITY; return; } // TODO 2的n次方 -- 直接copy的hashMap的代碼,這個有點困難。 this.capacity = tableSizeFor(capacity); } // 這個方法有點難實現,直接copy吧。 /** {@link java.lang.HashMap#tableSizeFor(int)} */ private int tableSizeFor(int capacity) { int n = capacity - 1; n |= n >>> 1; n |= n >>> 2; n |= n >>> 4; n |= n >>> 8; n |= n >>> 16; return (n < 0) ? 1 : (n >= MAX_CAPACITY) ? MAX_CAPACITY : n + 1; } private void vertiryConsturctorLoadFactor(float factor){ if (factor <= 0 || Float.isNaN(factor)) { throw new IllegalArgumentException("增加因子不合法"); } this.loadFactor = factor; } @SuppressWarnings({ "rawtypes", "unchecked" }) private void ifIncrement(){ if (capacitySize <= size) { // 擴容 Node<K, V>[] newTable = new Node[table.length * INCREMENT_FACTOR]; // 遍歷數組 for(Node<K, V> node : table){ if (node != null) { // 遍歷鏈表 for (Node<K, V> tempNode = node; tempNode != null; tempNode = tempNode.nextNode) { int indexOfTable = indexOfTable(tempNode.hash); Node<K, V> firstNode = newTable[indexOfTable]; if (firstNode == null ) { newTable[indexOfTable] = tempNode; }else{ newTable[indexOfTable] = new Node(tempNode.k, tempNode.v, tempNode.hash, firstNode); } } } } table = newTable; capacitySize = (int)(table.length * loadFactor); } } // 得到更好的hash散列 private int hash(int h){ // TODO return h; } // hash值對應的數組的位置 private int indexOfTable(int hash){ return hash & (table.length -1); } private Node<K, V> removeKey(Object key){ for (int i = 0; i < table.length; i++) { Node<K, V> node = table[i]; if (node == null) { continue; }else{ // 鏈表的第一個元素 if (key == null && node.k == null || key != null && node.k != null && key.hashCode() == node.k.hashCode() && key.equals(node.k)) { table[i] = node.nextNode; size--; modCount++; return node; }else{ // 鏈表的非第一個元素 Node<K, V> preNode = node; Node<K, V> tempNode = node.nextNode; while (tempNode != null) { if (key == null && tempNode.k == null || key != null && tempNode.k != null && key.hashCode() == tempNode.k.hashCode() && key.equals(tempNode.k)) { preNode.nextNode = tempNode.nextNode; size--; modCount++; return tempNode; } preNode = tempNode; tempNode = tempNode.nextNode; } } } } return null; } @SuppressWarnings("hiding") private class Node<K, V> { K k; V v; Node<K, V> nextNode; int hash; public Node(K k, V v, int hash, Node<K, V> nextNode) { this.k = k; this.v = v; this.hash = hash; this.nextNode = nextNode; } } private class Entry implements java.util.Map.Entry<K, V> { Node<K, V> node; public Entry(Node<K, V> node) { this.node = node; } @Override public K getKey() { return node.k; } @Override public V getValue() { return node.v; } @Override public V setValue(V value) { return node.v = value; } } private class EntrySet implements Set<java.util.Map.Entry<K, V>> { @Override public int size() { return MyHashMap.this.size(); } @Override public boolean isEmpty() { return MyHashMap.this.isEmpty(); } @Override public boolean contains(Object o) { return false; } @Override public Iterator<java.util.Map.Entry<K, V>> iterator() { return new MyIterator(); } @Override public Object[] toArray() { Object[] array = new Object[MyHashMap.this.size]; int index = 0; Iterator<java.util.Map.Entry<K, V>> iterator = this.iterator(); for (java.util.Map.Entry<K, V> entry = iterator.next(); iterator.hasNext(); ){ array[index++] = entry; } return array; } @SuppressWarnings("unchecked") @Override public <T> T[] toArray(T[] a) { int index = 0; Iterator<java.util.Map.Entry<K, V>> iterator = this.iterator(); for (java.util.Map.Entry<K, V> entry = iterator.next(); iterator.hasNext(); ){ if (index < a.length) { a[index++] = (T)entry; }else{ break; } } return a; } @Override public boolean add(java.util.Map.Entry<K, V> e) { return false; } @Override public boolean remove(Object o) { return false; } @Override public boolean containsAll(Collection<?> c) { return false; } @Override public boolean addAll(Collection<? extends java.util.Map.Entry<K, V>> c) { return false; } @Override public boolean retainAll(Collection<?> c) { return false; } @Override public boolean removeAll(Collection<?> c) { return false; } @Override public void clear() { MyHashMap.this.clear(); } public class MyIterator implements Iterator<java.util.Map.Entry<K, V>> { private int curreantIndexOfTable = 0; private Node<K, V> nextReturnNode = table[0]; private Node<K, V> lastReturnedNode; private int itrModCount = modCount; @Override public boolean hasNext() { return linkHasNext(nextReturnNode); } @Override public java.util.Map.Entry<K, V> next() { checkModCount(); lastReturnedNode = nextReturnNode; nextReturnNode = nextReturnNode.nextNode; compareNext(); return new Entry(lastReturnedNode); } @Override public void remove(){ MyHashMap.this.remove(lastReturnedNode.k); itrModCount = modCount; } private boolean linkHasNext(Node<K, V> nextReturnNode){ return nextReturnNode != null; } private void checkModCount(){ if (this.itrModCount != MyHashMap.this.modCount) throw new RuntimeException("遍歷期間不能刪元素,若是須要,請使用iterator.remove()"); } private void compareNext(){ if (! linkHasNext(nextReturnNode)) { boolean hashNext = false; while (!hashNext && ++curreantIndexOfTable < table.length) { nextReturnNode = table[curreantIndexOfTable]; hashNext = linkHasNext(nextReturnNode); } } } } } private class KeySet implements Set<K>{ @Override public int size() { return MyHashMap.this.size(); } @Override public boolean isEmpty() { return MyHashMap.this.isEmpty(); } @Override public boolean contains(Object o) { return MyHashMap.this.containsKey(o); } @Override public Iterator<K> iterator() { return new MyKeyIterator(); } @Override public Object[] toArray() { Object[] array = new Object[size]; int index = 0; Iterator<K> iterator = this.iterator(); for (K k = iterator.next(); iterator.hasNext(); ){ array[index++] = k; } return array; } @SuppressWarnings("unchecked") @Override public <T> T[] toArray(T[] a) { int index = 0; Iterator<K> iterator = this.iterator(); for (K k = iterator.next(); iterator.hasNext(); ){ if (index < a.length) { a[index++] = (T)k; }else{ break; } } return a; } @Override public boolean add(K e) { return false; } @Override public boolean remove(Object o) { return MyHashMap.this.removeKey(o) != null; } @Override public boolean containsAll(Collection<?> c) { for (Object object : c.toArray()) { if (! this.contains(object)) { return false; } } return true; } @Override public boolean addAll(Collection<? extends K> c) { return false; } @Override public boolean retainAll(Collection<?> c) { boolean changed = false; for (Object obj : c.toArray()) { changed |= this.contains(obj) ? this.remove(obj) : false; } return changed; } @Override public boolean removeAll(Collection<?> c) { boolean changed = false; for (Object object : c.toArray()) { changed |= this.remove(object); } return changed; } @Override public void clear() { MyHashMap.this.clear(); } private class MyKeyIterator implements Iterator<K> { Iterator<java.util.Map.Entry<K, V>> iterator = MyHashMap.this.entrySet().iterator(); @Override public boolean hasNext() { return iterator.hasNext(); } @Override public K next() { return iterator.next().getKey(); } @Override public void remove(){ iterator.remove(); } } } }
寫完HashSet再寫HashMap就比較簡單了,HashMap的Node節點無非就是多了一個value來表示鍵值對。JDK中的HashSet的實現就是直接使用的HashMap,value=new Object(),而後把key-value鍵值對存起來。關於HashMap的基本原理,請參考系列文章(一)。關於HashMao的遍歷方式,請參考系列文章(二)。java