1.hashmap的實現node
① 初始化數組
1)定義一個Node<K, V>的數組來存放元素,但不當即初始化,在使用的時候再加載ide
2)定義數組初始大小爲16測試
3)定義負載因子,默認爲0.75,this
4)定義size用來記錄容器存放的元素數量spa
② put的實現思路code
1) 判斷容器是否爲空,爲空則初始化。對象
2)判斷容器的size是否大於閥值,是的話就擴容爲之前長度的兩倍,並從新計算其中元素的存放位置,進行從新存放blog
3)計算出key的index角標位置get
4)判斷計算出的index位置是否存在元素,存在的話則遍歷鏈表,判斷key是否存在,存在則更新,不存在則增長
③ get的實現思路
1)經過key計算出它所在的index
2)遍歷index位置處的鏈表,並獲取value返回。
package com.test; /** * 自定義hashMap * @author cf * * @param <K> * @param <V> */ public class MyHashMap<K, V> implements MyMap<K, V>{ //1.定義一個容器用來存放元素, 但不當即初始化,使用懶加載方式 Node<K, V>[] table = null; //2.定義容器的默認大小 static int DEFAULT_INITIAL_CAPACITY = 16; //3.HashMap默認負載因子,負載因子越小,hash衝突機率越低,綜合結論得出0.75最爲合適 static final float DEFAULT_LOAD_FACTOR = 0.75f; //4.記錄當前容器實際大小 static int size; @SuppressWarnings("unchecked") @Override public V put(K k, V v) { //1.判斷容器是否爲空爲空則初始化。 if (table == null) { table = new Node[DEFAULT_INITIAL_CAPACITY]; } //若是size大於閾值則進行擴容 if (size > DEFAULT_INITIAL_CAPACITY * DEFAULT_LOAD_FACTOR) { resize(); } //2.計算出index角標 int index = getIndex(k, DEFAULT_INITIAL_CAPACITY); //3.將k-v鍵值對放進相對應的角標,若是計算出角標相同則以鏈表的形勢存放 Node<K, V> node = table[index]; if (node == null) { table[index] = new Node<>(k, v, null); size ++; return table[index].getValue(); } else { Node<K, V> newNode = node; //循環遍歷每一個節點看看是否存在相同的key while (newNode != null) { //這裏要用equals 和 == 由於key有多是基本數據類型,也有多是引用類型 if (k.equals(newNode.getKey()) || k == newNode.getKey()) { newNode.setValue(v); size ++; return v; } newNode = node.getNextNode(); } table[index] = new Node<K, V>(k, v, table[index]); size ++; return table[index].getValue(); } } /** * 獲取index * @param key * @param length * @return */ public int getIndex(K key, int length) { int hashCode = key.hashCode(); int index = hashCode % length; return index; } /** * 獲取key */ @Override public V get(K k) { int index = getIndex(k, DEFAULT_INITIAL_CAPACITY); Node<K, V> node = table[index]; if (k.equals(node.getKey()) || k == node.getKey()) { return node.getValue(); } else { Node<K, V> nextNode = node.getNextNode(); while(nextNode != null) { if (k.equals(nextNode.getKey()) || k == nextNode.getKey()) { return nextNode.getValue(); } } } return null; } /** * 對size進行擴容 */ @SuppressWarnings("unchecked") public void resize() { //1.建立新的table長度擴展爲之前的兩倍 int newLength = DEFAULT_INITIAL_CAPACITY * 2; Node<K, V>[] newtable = new Node[newLength]; //2.將之前table中的取出,並從新計算index存入 for (int i = 0; i < table.length; i++) { Node<K, V> oldtable = table[i]; while (oldtable != null) { //將table[i]的位置賦值爲空, table[i] = null; //方法1:從新計算index,而後按照put時候的方法進行放值,此種方法會不停的new 對象會形成效率比較低 /*K key = oldtable.getKey(); int index = getIndex(key, newLength); newtable[index] = new Node<K, V>(key, oldtable.getValue(), newtable[index]); oldtable = oldtable.getNextNode();*/ //方法2: //計算新的index值 K key = oldtable.getKey(); int index = getIndex(key, newLength); //將之前的nextnode保存下來 Node<K, V> nextNode = oldtable.getNextNode(); //將newtable的值賦值在oldtable的nextnode上,若是之前是空,則nextnode也是空 oldtable.setNextNode(newtable[index]); newtable[i] = oldtable; //將之前的nextcode賦值給oldtable以便繼續遍歷 oldtable = nextNode; } } //3.將新的table賦值回老的table table = newtable; DEFAULT_INITIAL_CAPACITY = newLength; newtable = null; } @Override public int size() { return size; } @SuppressWarnings("hiding") class Node<K, V> implements Entry<K, V> { private K key; private V value; private Node<K, V> nextNode; //下一節點 public Node(K key, V value, Node<K, V> nextNode) { super(); this.key = key; this.value = value; this.nextNode = nextNode; } @Override public K getKey() { return this.key; } @Override public V getValue() { return this.value; } @Override public void setValue(V value) { this.value = value; } public Node<K, V> getNextNode() { return nextNode; } public void setNextNode(Node<K, V> nextNode) { this.nextNode = nextNode; } public void setKey(K key) { this.key = key; } //判斷是否還有下一個節點 /*private boolean hasNext() { return true; }*/ } // 測試方法.打印全部的鏈表元素 public void print() { for (int i = 0; i < table.length; i++) { Node<K, V> node = table[i]; System.out.print("下標位置[" + i + "]"); while (node != null) { System.out.print("[ key:" + node.getKey() + ",value:" + node.getValue() + "]"); node = node.nextNode; } System.out.println(); } } }
2.測試代碼
package com.test; public class TestMap { public static void main(String[] args) { MyHashMap<String, String> extHashMap = new MyHashMap<String, String>(); extHashMap.put("1號", "1號");// 0 extHashMap.put("2號", "1號");// 1 extHashMap.put("3號", "1號");// 2 extHashMap.put("4號", "1號");// 3 extHashMap.put("6號", "1號");// 4 extHashMap.put("7號", "1號"); extHashMap.put("14號", "1號"); extHashMap.put("22號", "1號"); extHashMap.put("26號", "1號"); extHashMap.put("27號", "1號"); extHashMap.put("28號", "1號"); extHashMap.put("66號", "66"); extHashMap.put("30號", "1號"); System.out.println("擴容前數據...."); extHashMap.print(); System.out.println("擴容後數據...."); extHashMap.put("31號", "1號"); extHashMap.put("66號", "123466666"); extHashMap.print(); // 修改3號以後 System.out.println(extHashMap.get("66號")); } }
若有疑問或錯誤請在下方留言指出! 謝謝大佬