首頁>技術>

來源: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();   }}

最新評論
  • BSA-TRITC(10mg/ml) TRITC-BSA 牛血清白蛋白改性標記羅丹明
  • Vue文件筆記系列——可複用性&組合