Java 手寫設計HashMap源碼,讓面試官膜拜

Java 手寫HashMap源碼,讓面試官膜拜

一,手寫源碼

這是一個模仿HashMap的put,get功能的自定義的MyHashMap

package cn.wxs.demo;import java.io.Serializable;
import java.util.*;
import java.util.function.BiConsumer;class MyHashMap<K, V> extends AbstractMap<K,V>implements Map<K,V>, Cloneable, Serializable {private static final int DEFAULT_CAPACITY = 16;private static final float DEFAULT_LOAD_FACTOR = 0.75f;private Node<K, V>[] table; // 存儲桶數組private transient int size; // 鍵值對數量private transient int modCount;  //總數private transient int threshold; // 擴容閾值private float loadFactor; // 負載因子@Overridepublic void forEach(BiConsumer<? super K, ? super V> action) {MyHashMap.Node<K,V>[] tab;if (action == null)throw new NullPointerException();if (size > 0 && (tab = table) != null) {int mc = modCount;for (int i = 0; i < tab.length; ++i) {for (MyHashMap.Node<K,V> e = tab[i]; e != null; e = e.next)action.accept(e.key, e.value);}if (modCount != mc)throw new ConcurrentModificationException();}}public MyHashMap() {this(DEFAULT_CAPACITY, DEFAULT_LOAD_FACTOR);}public MyHashMap(int initialCapacity, float loadFactor) {if (initialCapacity <= 0)throw new IllegalArgumentException("Invalid initial capacity");if (loadFactor <= 0 || Float.isNaN(loadFactor))throw new IllegalArgumentException("Invalid load factor");this.table = new Node[initialCapacity];this.size = 0;this.loadFactor = loadFactor;this.threshold = (int) (initialCapacity * loadFactor);}public V get(Object key) {Node<K, V> node = getNode((K) key);return (node != null) ? node.value : null;}public V put(K key, V value) {if (key == null)putForNullKey(value);elseputNonNullKey(key, value);return value;}@Overridepublic Set<Entry<K, V>> entrySet() {return null;}private void putNonNullKey(K key, V value) {int hash = hash(key);int index = indexFor(hash, table.length);// 遍歷鏈表,查找是否已存在相同的鍵for (Node<K, V> node = table[index]; node != null; node = node.next) {if (node.hash == hash && Objects.equals(node.key, key)) {// 如果找到相同的鍵,更新對應的值node.value = value;return;}}// 如果沒有找到相同的鍵,將新的鍵值對添加到鏈表頭部addNode(hash, key, value, index);}private void putForNullKey(V value) {// 對于 null 鍵,存儲在數組的第一個位置for (Node<K, V> node = table[0]; node != null; node = node.next) {if (node.key == null) {// 如果找到 null 鍵,更新對應的值node.value = value;return;}}// 如果沒有找到 null 鍵,將新的鍵值對添加到鏈表頭部addNode(0, null, value, 0);}private void addNode(int hash, K key, V value, int bucketIndex) {// 檢查是否需要擴容if (size >= threshold)resize(2 * table.length);// 將新的節點添加到鏈表頭部Node<K, V> newNode = new Node<>(hash, key, value, table[bucketIndex]);table[bucketIndex] = newNode;size++;modCount++;}private Node<K, V> getNode(K key) {if (key == null)return getNodeForNullKey();int hash = hash(key);int index = indexFor(hash, table.length);// 遍歷鏈表,查找指定的鍵for (Node<K, V> node = table[index]; node != null; node = node.next) {if (node.hash == hash && Objects.equals(node.key, key))return node;}return null;}private Node<K, V> getNodeForNullKey() {// 對于 null 鍵,存儲在數組的第一個位置for (Node<K, V> node = table[0]; node != null; node = node.next) {if (node.key == null)return node;}return null;}private int hash(K key) {// 計算鍵的哈希值return (key == null) ? 0 : key.hashCode();}private int indexFor(int hash, int length) {// 根據哈希值和數組長度計算索引位置return hash & (length - 1);}private void resize(int newCapacity) {Node<K, V>[] oldTable = table;int oldCapacity = oldTable.length;// 檢查是否達到容量上限if (oldCapacity >= 1 << 30)threshold = Integer.MAX_VALUE;elsethreshold = (int) (newCapacity * loadFactor);// 創建新的數組,將舊的鍵值對重新分配到新的數組中Node<K, V>[] newTable = new Node[newCapacity];transfer(oldTable, newTable);table = newTable;}private void transfer(Node<K, V>[] src, Node<K, V>[] dest) {// 遍歷舊的數組,將鍵值對重新分配到新的數組中for (Node<K, V> node : src) {while (node != null) {Node<K, V> next = node.next;int index = indexFor(node.hash, dest.length);node.next = dest[index];dest[index] = node;node = next;}}}static class Node<K, V> {final int hash; // 哈希值final K key; // 鍵V value; // 值Node<K, V> next; // 下一個節點Node(int hash, K key, V value, Node<K, V> next) {this.hash = hash;this.key = key;this.value = value;this.next = next;}}public static void main(String[] args) {MyHashMap<String,String> param = new MyHashMap<>();param.put("你好","你好");param.put("你好1","你好1");param.put("你好2","你好2");param.put("你好3","你好3");param.put("你好4","你好4");param.put("你好5","你好4");param.put("你好6","你好4");param.put("你好7","你好4");param.put("你好8","你好4");param.put("你好9","你好4");param.put("你好10","你好4");param.put("你好11","你好4");param.put("你好12","你好4");param.put("你好13","你好4");param.put("你好14","你好4");param.put("你好15","你好4");param.put("你好16","你好4");param.put("你好17","你好4");param.put("你好18","你好4");param.put("你好20","你好4");param.put("你好21","你好4");param.put("你好22","你好4");param.put("你好23","你好4");param.put("你好24","你好4");param.put("你好25","你好4");param.put("你好26","你好4");param.put("你好27","你好4");param.put("你好28","你好4");param.put("你好29","你好4");param.put("你好30","你好4");param.put("你好31","你好4");param.put("你好32","你好4");param.forEach((k,v)-> System.out.println(k));
//        System.out.println(param.get("你好4"));}
}

在這里插入圖片描述

二,代碼介紹

1.這是一個簡單的自定義哈希映射(HashMap)的實現。功能不太完善,代碼不太優雅,細節不夠好,沒有源碼的那么好。后面我會慢慢進行優化
2.這段代碼實現了一個簡化版本的 HashMap,包含了 put 和 get 方法,并使用了數組+鏈表的存儲結構。注意,這里的紅黑樹部分并未實現,只使用了鏈表來處理沖突。由于短時間沒有辦法能按自己的方式寫出來全部的功能和底層設計,難度還是比較大的后期我會慢慢的把存儲結構改成數組+鏈表+紅黑樹的數據結構

請注意,這只是一個簡化版本的實現,并沒有處理擴容、紅黑樹轉換等復雜的細節。實際的 HashMap 實現要復雜得多。如果你對完整的實現感興趣,建議你查閱 Java 的 HashMap 源代碼,以便更好地理解和學習。

三,下期完善功能

size()
remove(key)
containsKey(key)
containsValue(value)

三,HashMap

HashMap 是 Java 中的一個常用的數據結構,它實現了 Map 接口,并且基于哈希表實現。HashMap 允許存儲鍵值對,并且提供了快速的插入、查找和刪除操作。

下面是 HashMap 的一些重要特點和概念:

  • 哈希表HashMap 內部使用了一個數組來存儲數據,這個數組被稱為哈希表。哈希表的每個元素稱為一個桶(bucket),每個桶可以存儲一個或多個鍵值對。通過計算鍵的哈希值,可以確定鍵值對在哈希表中的位置。

  • 哈希函數:哈希函數用于將鍵映射到哈希表中的索引位置。好的哈希函數能夠將鍵均勻地分布在哈希表的不同位置上,以減少沖突的概率。在 HashMap 中,鍵的 hashCode() 方法被用作哈希函數。

  • 沖突:當兩個不同的鍵通過哈希函數計算得到的索引位置相同時,就發生了沖突。HashMap 使用鏈表或紅黑樹來解決沖突。當沖突較少時,使用鏈表;當鏈表長度超過一定閾值時,轉換為紅黑樹,以提高查找的效率。

  • 鍵的唯一性:在 HashMap 中,鍵是唯一的。如果嘗試將一個已經存在的鍵插入到 HashMap 中,它的值將被更新為新的值。

  • null 鍵HashMap 允許存儲一個鍵為 null 的鍵值對。這個鍵將被存儲在哈希表的第一個位置上。

  • 迭代順序HashMap 不保證鍵值對的迭代順序,它通常是不確定的。如果需要有序的鍵值對集合,可以使用 LinkedHashMap

下面是一些常用的操作方法:

  • put(key, value):向 HashMap 中插入一個鍵值對。
  • get(key):根據鍵獲取對應的值。
  • remove(key):根據鍵刪除對應的鍵值對。
  • containsKey(key):檢查是否包含指定的鍵。
  • containsValue(value):檢查是否包含指定的值。
  • size():返回 HashMap 中鍵值對的數量。

需要注意的是,HashMap 是非線程安全的,如果在多線程環境中使用,需要進行適當的同步處理,或者使用線程安全的 ConcurrentHashMap

HashMap 的時間復雜度通常是常數級別的,即 O(1),但在最壞的情況下,可能會達到 O(n),其中 n 是 HashMap 中存儲的鍵值對數量。

希望這個簡介對你理解 HashMap 有所幫助!如果你有任何其他問題,請隨時提問。

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/212423.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/212423.shtml
英文地址,請注明出處:http://en.pswp.cn/news/212423.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

面向對象三大特征——封裝

目錄 1. 封裝概述&#xff08;封裝與隱藏&#xff09; 2. private關鍵字 3. Getter & Setter方法 4. 變量訪問原則和this關鍵字 5. 構造方法 5.1 構造方法概述 5.2 構造方法和set方法的比較 6. 靜態 6.1 靜態概述 6.2 靜態效果 6.3 靜態變量和非靜態變量的區別 …

win11 CUDA(12.3) + cuDNN(12.x) 卸載

win11 CUDA&#xff08;12.3&#xff09; cuDNN&#xff08;12.x&#xff09;卸載 信息介紹卸載 信息介紹 本文是對應 win11RTX4070Ti 安裝 CUDA cuDNN&#xff08;圖文教程&#xff09; 的卸載 卸載 控制面板 --> 程序 --> 卸載程序 卸載掉圖中紅框內的&#xff0c…

C語言-水仙花數

水仙花數是指一個N位正整數&#xff08;N≥3&#xff09;&#xff0c;它的每個位上的數字的N次冪之和等于它本身。例如&#xff1a;153135333。 本題要求編寫程序,計算所有N位水仙花數。 輸入格式: 輸入在一行中給出一個正整數N&#xff08;3≤N≤7&#xff09;。 輸出格式…

reinforce 跑 CartPole-v1

gym版本是0.26.1 CartPole-v1的詳細信息&#xff0c;點鏈接里看就行了。 修改了下動手深度強化學習對應的代碼。 然后這里 J ( θ ) J(\theta) J(θ)梯度上升更新的公式是用的不嚴謹的&#xff0c;這個和王樹森書里講的嚴謹公式有點區別。 代碼 import gym import torch from …

innobackupex備份目錄

innobackupeex全備腳本思路 四個需求如下&#xff1a; &#xff08;1&#xff09;每天晚上23點執行&#xff0c;這需要linux系統做一個定時任務 00 23 * * * /bin/sh /shell/tencent_xtrabackup_all.sh /dev/null 2>&1 &#xff08;2&#xff09;每天。。看到這個詞…

標識符···

定義 標識符只能由字母、數字、下劃線&#xff08;_&#xff09;和美元符號&#xff08;$&#xff09;組成。標識符必須以字母、下劃線或美元符號開頭&#xff0c;不能以數字開頭。標識符對大小寫敏感&#xff0c;例如"myVariable"和"myvariable"是不同的…

Android 11 適配——整理總結篇

背景 > 經過檢測&#xff0c;我們識別到您的應用&#xff0c;目前未適配安卓11&#xff08;API30&#xff09;&#xff0c;請您關注適配截止時間&#xff0c;盡快開展適配工作&#xff0c;避免影響應用正常發布和經營。 > targetSdkVersion30 升級適配工作參考文檔&am…

從零開發短視頻電商 Jmeter壓測示例模板詳解(無認證場景)

文章目錄 添加線程組添加定時器添加HTTP請求默認值添加HTTP頭管理添加HTTP請求添加結果斷言響應斷言 Response AssertionJSON斷言 JSON Assertion持續時間斷言 Duration Assertion 添加察看結果樹添加聚合報告添加表格察看結果參考 以壓測百度搜索為例 https://www.baidu.com/s…

class066 一維動態規劃【算法】

class066 一維動態規劃 算法講解066【必備】從遞歸入手一維動態規劃 code1 509斐波那契數列 // 斐波那契數 // 斐波那契數 &#xff08;通常用 F(n) 表示&#xff09;形成的序列稱為 斐波那契數列 // 該數列由 0 和 1 開始&#xff0c;后面的每一項數字都是前面兩項數字的和。…

kotlin - ViewBinding

前言 為什么用ViewBinding&#xff0c;而不用findViewById()&#xff0c;這個有很多優秀的博主都做了講解&#xff0c;就不再列出了。 可參考下列博主的文章&#xff1a; kotlin ViewBinding的使用 文章里也給出了如何在gradle中做出相應的配置。 &#xff08;我建議先看這位博…

【LeetCode熱題100】【滑動窗口】無重復字符的最長子串

給定一個字符串 s &#xff0c;請你找出其中不含有重復字符的 最長子串 的長度。 示例 1: 輸入: s "abcabcbb" 輸出: 3 解釋: 因為無重復字符的最長子串是 "abc"&#xff0c;所以其長度為 3。示例 2: 輸入: s "bbbbb" 輸出: 1 解釋: 因為無…

Docker安裝教程

docker官網 1.卸載舊版 yum remove docker \docker-client \docker-client-latest \docker-common \docker-latest \docker-latest-logrotate \docker-logrotate \docker-engine2.配置Docker的yum庫 安裝yum工具 yum install -y yum-utils配置Docker的yum源 yum-config-ma…

Redis,什么是緩存穿透?怎么解決?

Redis&#xff0c;什么是緩存穿透&#xff1f;怎么解決&#xff1f; 1、緩存穿透 一般的緩存系統&#xff0c;都是按照key去緩存查詢&#xff0c;如果不存在對用的value&#xff0c;就應該去后端系統查找&#xff08;比如DB數據庫&#xff09;。一些惡意的請求會故意查詢不存在…

不想寫大量 if 判斷?試試用規則執行器優化,就很絲滑!

近日在公司領到一個小需求&#xff0c;需要對之前已有的試用用戶申請規則進行拓展。我們的場景大概如下所示: if (是否海外用戶) {return false; }if (刷單用戶) {return false; }if (未付費用戶 && 不再服務時段) {return false }if (轉介紹用戶 || 付費用戶 || 內推…

16ASM 分段和機器碼

8086CPU存儲分段管理 問題1&#xff1a;8086是16位cpu&#xff0c;最多可訪問&#xff08;尋址&#xff09;多大內存&#xff1f; 運算器一次最多處理16位的數據。地址寄存器的最大寬度為16位。訪問的最大內存為&#xff1a;216 64K 即 0000 - FFFF。 問題2&#xff1a;808…

Hadoop集群破壞試驗可靠性驗證

集群環境說明&#xff1a; 準備5臺服務器&#xff0c;hadoop1、hadoop2、hadoop3、hadoop4、hadoop5&#xff1b; 分別部署5個節點的zookeeper集群、hadoop集群、hbase集群 本次對于Hadoop集群測試主要分為五個方面&#xff1a; 手動進行datanode節點刪除&#xff1a;&#…

typedef 與#define 的區別

typedef 與#define 的區別 typedef &#xff1a; 給一個已經存在的數據類型&#xff08;注意&#xff1a;是類型不是變量&#xff09;取一個別名&#xff0c;而非定義一個新的數據類型 #define宏定義&#xff1a; #define宏定義&#xff1a;在預編譯時直接進行簡單的文本替換 舉…

WIFI直連(Wi-Fi P2P)

一、概述 Wifi peer-to-peer&#xff08;也稱Wifi-Direct&#xff09;是Wifi聯盟推出的一項基于原來WIfi技術的可以讓設備與設備間直接連接的技術&#xff0c;使用戶不需要借助局域網或者AP&#xff08;Access Point&#xff09;就可以進行一對一或一對多通信。這種技術的應用…

計算機畢業設計 SpringBoot的樂樂農產品銷售系統 Javaweb項目 Java實戰項目 前后端分離 文檔報告 代碼講解 安裝調試

&#x1f34a;作者&#xff1a;計算機編程-吉哥 &#x1f34a;簡介&#xff1a;專業從事JavaWeb程序開發&#xff0c;微信小程序開發&#xff0c;定制化項目、 源碼、代碼講解、文檔撰寫、ppt制作。做自己喜歡的事&#xff0c;生活就是快樂的。 &#x1f34a;心愿&#xff1a;點…

Xmanager

什么是 XManager Xmanager 是市場上領先的 PC X 服務器&#xff0c;可將X應用程序的強大功能帶入 Windows 環境。 提供了強大的會話管理控制臺&#xff0c;易于使用的 X 應用程序啟動器&#xff0c;X 服務器配置文件管理工具&#xff0c;SSH 模塊和高性能 PC X 服務器。 Xman…