來源:https://www.tuicool.com/articles/FbeyymJ
你好,早上、中午、下午、晚上好。我是獅子王辛巴。一名無緣985,日常996工程師。
作為一名為人民幣服務的工程師,學好技術是多麼重要的事情。 今天跟各位老鐵們詳細說說日常的開發中經常用到的HashMap。
怎麼可能騙你,真的哦,無論我們在開發中還是在面試的時候HashMap比問好不好。上次“娜娜”去熊廠 就被面試官問到了,被虐的體無完膚。
哼~ 哼 ~哼 哼 哼 哼 哼
~哼~~~~
娜娜寶貝別生氣了,辛巴哥哥現場教學了。 首先我們快速回憶下我們日常開發中怎麼使用hashmap的。
快速開始public class App { public static void main(String[] args) { //Map map = new HashMap<>(); App map=new App(); map.put("劉一", "劉一"); map.put("陳二", "陳二"); map.put("張三", "張三"); map.put("李四", "李四"); map.put("王五", "王五"); map.put("java_jiagou", "微信搜:java大型網站架構"); System.out.println(map.get("java_jiagou")); }
hashmap在我們日常工作一般用的多的就是其put方法和get方法。
技術本質現在我們已經對hashmap有一個大致的了解了,接下來我們要去了解其底層的原理,也就是本質。
很多朋友在面試的時候經常被問到hashmap底層實現原理?都說是資料+連結串列 ok!估計大家都會被了 但是真正知道底層如何儲存的我相信不多,不急 我們來看下陣列和連結串列的定義
陣列陣列:採用一段連續的儲存單元來儲存資料。對於指定下標的查詢,時間複雜度為O(1);對於一般的插入刪除操作, 涉及到陣列元素的移動,其平均複雜度也為O(n)
Java程式碼表示
//陣列:採用一段連續的儲存單元來儲存資料。 //特點:指定下標O(1) 刪除插入O(N) 陣列:查詢快 插入慢 ArrayList public static void main(String[] args) { Integer[] integers = new Integer[10]; integers[0]=0;//王五 integers[1]=1; integers[2]=2; integers[9]=9;
連結串列
連結串列是一種物理儲存單元上非連續、非順序的儲存結構,資料元素的邏輯順序是通過連結串列中的指標連結次序實現的 對於連結串列的新增,刪除等操作(在找到指定操作位置後),僅需處理結點間的引用即可,時間複雜度為O(1), 而查詢操作需要遍歷連結串列逐一進行比對,複雜度為O(n)
public class Node { public Node next; private Object data; public Node(Object data) { this.data = data; } //連結串列:連結串列是一種物理儲存單元上非連續、非順序的儲存結構 //特點:插入、刪除時間複雜度O(1) 查詢遍歷時間複雜度0(N) 插入快 查詢慢 public static void main(String[] args) { Node node=new Node(15); node.next=new Node(1); node.next.next=new Node(9); }
雜湊演算法雜湊演算法(也叫雜湊),就是把任意長度值(Key)通過雜湊演算法變換成固定長度的key地址,通過這個地址進行訪問的資料結構。 它通過把關鍵碼值對映到表中一個位置來訪問記錄,以加快查詢的速度。
實現原理PUT剛才我們分析了hashmap由陣列+連結串列構成,介紹了陣列+連結串列的描述,接下來我們就把這兩個資料結構整合在一起吧,在整合在一起 我們寫一個偽put程式碼,目的是看hahsmap底層儲存
/*** * 輸出 key value hashcode 等 hash演算法 * @param key * @param value */ public void put(String key, String value) { //hash函式 System.out.printf("key:%s,hash值:%s,儲存位置:%s\\r\\n", key, key.hashCode(), Math.abs(key.hashCode() % 15)); }
執行程式碼如下
key:劉一,hash值:671464,儲存位置:4key:陳二,hash值:1212740,儲存位置:5key:張三,hash值:774889,儲存位置:4key:李四,hash值:842061,儲存位置:6key:王五,hash值:937065,儲存位置:0key:java_jiagou,hash值:1185548040,儲存位置:0
對應的圖形儲存結構就是:
**1. 初始化:
2. 第一次put:
這次put“劉一” 存放在下標為4的陣列上,物件型別是
class Entry<K, V> K k; V v; int hash; Entry<K, V> next;
key:劉一,hash值:671464,儲存位置:4
第二次put:
這次put“陳二” 存放在下標為5的陣列上
key:陳二,hash值:1212740,儲存位置:5
第三次put: 這次次put“張三” 存放在下標為4的陣列上,可是下標為4已經有“劉一”了,如果暴力儲存會出問題的呀。 別急嘛,我們剛才不是還學了連結串列嘛。這個時候該連結串列上場了。
key:張三,hash值:774889,儲存位置:4
第N次put: 我相信通過前幾次的put大家都會put了吧,最後儲存結構是這樣的。
實現原理GET我們put是根據hash演算法定位到陣列下標的,那我們get怎麼找到他們了?非常簡單嘛原路去找 盡然可以通過hash演算法put,肯定也可以通過hash演算法get到嘛。A點盡然可以到B點,那自然B點也可以到A點嘛。示範一個,只示範一個。
實現娜娜你聽懂了嘛?
哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈!快到碗裡來吧
總結好了各位,以上就是這篇文章的全部內容了,能看到這裡的人呀,都是牛人。那我在佈置個作業吧。 根據我們圖形的演示,你能手寫實現嗎?
我提示下
public interface Map<K,V> { public V put(K k,V v); public V get(K k); public int size(); interface Entry<K,V>{ public K getKey(); public V getValue(); }}