Java怎麼根據key值修改Hashmap中的value值
根據key值修改Hashmap的value值
#如果原來map中沒有key,會創建,如果原來有key,會使用value 覆寫原來的值
map.put(key,value);
這個實作對原值加一(前提是有這個key)
map.put(key,map.get(key)+1);
以下可以取得key對應的value,如果沒有可以回傳預設的value
map.getOrDefault(key,value);
HashMap的key更改後能否正確取得value?
在HashMap 中存放的一系列鍵值對,其中鍵為某個我們自訂的類型。放入 HashMap 後,我們在外部把某一個 key 的屬性進行更改,然後我們再用這個 key 從 HashMap 裡取出元素,這時候 HashMap 會回傳什麼?
我們辦公室幾個人答案都不一致,有的說返回null,有的說能正常返回value。但不論答案是什麼都沒有確切的理由。我覺得這個問題蠻有趣的,就寫了程式碼測試。結果是回傳null。需要說明的是我們自訂的類別重寫了 hashCode 方法。我想這個結果還是有點意外的,因為我們知道HashMap 存放的是引用類型,我們在外面把key 更新了,那也就是說HashMap 裡面的key 也更新了,也就是這個key 的hashCode 回傳值也會發生變化。這時候 key 的 hashCode 和 HashMap 對於元素的 hashCode 肯定一樣,equals也肯定回傳true,因為本來就是同一個對象,那為什麼不能回傳正確的值呢?
測試案例
這裡有2 個案例,一個是Person 類,還有一個是Student 類,我們來驗證下以上的觀點(附帶結論):
修改了物件屬性是否會改變它的hashcode => 是的
在HashMap 裡訪問的時候是否會受到修改屬性影響取值=> ; 取值為null
package tech.luxsun.interview.luxinterviewstarter.collection; import lombok.AllArgsConstructor; import lombok.Data; import lombok.NoArgsConstructor; import java.util.HashMap; /** * @author Lux Sun * @date 2021/4/22 */ public class MapDemo0 { public static void main(String[] args) { HashMap<Object, Object> map = new HashMap<>(); // Person Case Person p = new Person("Bob", 12); map.put(p, "person"); System.out.println(p.hashCode()); System.out.println(map.get(p)); p.setAge(13); System.out.println(p.hashCode()); System.out.println(map.get(p)); // Student Case Student stu = new Student("Bob", 12); map.put(stu, "student"); System.out.println(stu.hashCode()); System.out.println(map.get(stu)); stu.setAge(13); System.out.println(stu.hashCode()); System.out.println(map.get(stu)); } } @Data @AllArgsConstructor @NoArgsConstructor class Person { private String name; private Integer age; public int hashCode() { return 123456; } } @Data @AllArgsConstructor @NoArgsConstructor class Student { private String name; private Integer age; }
輸出結果
#123456
person
123456
person
71154
student
71213
null
原始碼
hashCode 原始碼
public int hashCode() { int PRIME = true; int result = 1; Object $age = this.getAge(); int result = result * 59 + ($age == null ? 43 : $age.hashCode()); Object $name = this.getName(); result = result * 59 + ($name == null ? 43 : $name.hashCode()); return result; }
map.get 原始碼
/** * Returns the value to which the specified key is mapped, * or {@code null} if this map contains no mapping for the key. * * <p>More formally, if this map contains a mapping from a key * {@code k} to a value {@code v} such that {@code (key==null ? k==null : * key.equals(k))}, then this method returns {@code v}; otherwise * it returns {@code null}. (There can be at most one such mapping.) * * <p>A return value of {@code null} does not <i>necessarily</i> * indicate that the map contains no mapping for the key; it's also * possible that the map explicitly maps the key to {@code null}. * The {@link #containsKey containsKey} operation may be used to * distinguish these two cases. * * @see #put(Object, Object) */ public V get(Object key) { Node<K,V> e; return (e = getNode(hash(key), key)) == null ? null : e.value; } /** * Computes key.hashCode() and spreads (XORs) higher bits of hash * to lower. Because the table uses power-of-two masking, sets of * hashes that vary only in bits above the current mask will * always collide. (Among known examples are sets of Float keys * holding consecutive whole numbers in small tables.) So we * apply a transform that spreads the impact of higher bits * downward. There is a tradeoff between speed, utility, and * quality of bit-spreading. Because many common sets of hashes * are already reasonably distributed (so don't benefit from * spreading), and because we use trees to handle large sets of * collisions in bins, we just XOR some shifted bits in the * cheapest possible way to reduce systematic lossage, as well as * to incorporate impact of the highest bits that would otherwise * never be used in index calculations because of table bounds. */ static final int hash(Object key) { int h; return (key == null) ? 0 : (h = key.hashCode()) ^ (h >>> 16); } /** * Implements Map.get and related methods * * @param hash hash for key * @param key the key * @return the node, or null if none */ final Node<K,V> getNode(int hash, Object key) { Node<K,V>[] tab; Node<K,V> first, e; int n; K k; if ((tab = table) != null && (n = tab.length) > 0 && (first = tab[(n - 1) & hash]) != null) { if (first.hash == hash && // always check first node ((k = first.key) == key || (key != null && key.equals(k)))) return first; if ((e = first.next) != null) { if (first instanceof TreeNode) return ((TreeNode<K,V>)first).getTreeNode(hash, key); do { if (e.hash == hash && ((k = e.key) == key || (key != null && key.equals(k)))) return e; } while ((e = e.next) != null); } } return null; }
總之
可以看到先取得了一個table,這個table其實是個陣列。然後在table裡面找對應 key 的value。找的標準就是hash等於傳入參數的hash, 並且滿足另外兩個條件之一:k = e.key,也就是說他們是同一個對象,或是傳入的 key 的equal目標的 key 。我們的問題出在那個hash(key.hashCode()),可以看到 HashMap 在儲存元素時是把 key 的 hashCode 再做了一次hash。得到的hash將最終作為元素儲存位置的依據。對應到我們的情況:第一次儲存時,hash函數採用key.hashCode作為參數得到了一個值,然後根據這個值把元素存到了某個位置。
當我們再去取元素的時候,key.hashCode的值已經出現了變化,所以這裡的hash函數結果也發生了變化,所以當它嘗試去獲得這個key 的存儲位置時就不能得到正確的值,導致最終找不到目標元素。要想能正確返回,很簡單,把Person類別的hashCode 方法改一下,讓它的hashCode 不依賴我們要修改的屬性,但實際開發中肯定不能這麼幹,我們總是希望當兩個物件的屬性不完全相同時能傳回不同的hashCode 值。
所以結論就是當把物件放到 HashMap 後,不要去修改 key 的屬性,除非你重寫了該實體類別的 hashCode 方法不受屬性限制。
以上是Java怎麼根據key值修改Hashmap中的value值的詳細內容。更多資訊請關注PHP中文網其他相關文章!

熱AI工具

Undresser.AI Undress
人工智慧驅動的應用程序,用於創建逼真的裸體照片

AI Clothes Remover
用於從照片中去除衣服的線上人工智慧工具。

Undress AI Tool
免費脫衣圖片

Clothoff.io
AI脫衣器

Video Face Swap
使用我們完全免費的人工智慧換臉工具,輕鬆在任何影片中換臉!

熱門文章

熱工具

記事本++7.3.1
好用且免費的程式碼編輯器

SublimeText3漢化版
中文版,非常好用

禪工作室 13.0.1
強大的PHP整合開發環境

Dreamweaver CS6
視覺化網頁開發工具

SublimeText3 Mac版
神級程式碼編輯軟體(SublimeText3)

Java 8引入了Stream API,提供了一種強大且表達力豐富的處理數據集合的方式。然而,使用Stream時,一個常見問題是:如何從forEach操作中中斷或返回? 傳統循環允許提前中斷或返回,但Stream的forEach方法並不直接支持這種方式。本文將解釋原因,並探討在Stream處理系統中實現提前終止的替代方法。 延伸閱讀: Java Stream API改進 理解Stream forEach forEach方法是一個終端操作,它對Stream中的每個元素執行一個操作。它的設計意圖是處

PHP是一種廣泛應用於服務器端的腳本語言,特別適合web開發。 1.PHP可以嵌入HTML,處理HTTP請求和響應,支持多種數據庫。 2.PHP用於生成動態網頁內容,處理表單數據,訪問數據庫等,具有強大的社區支持和開源資源。 3.PHP是解釋型語言,執行過程包括詞法分析、語法分析、編譯和執行。 4.PHP可以與MySQL結合用於用戶註冊系統等高級應用。 5.調試PHP時,可使用error_reporting()和var_dump()等函數。 6.優化PHP代碼可通過緩存機制、優化數據庫查詢和使用內置函數。 7

PHP和Python各有優勢,選擇應基於項目需求。 1.PHP適合web開發,語法簡單,執行效率高。 2.Python適用於數據科學和機器學習,語法簡潔,庫豐富。

PHP適合web開發,特別是在快速開發和處理動態內容方面表現出色,但不擅長數據科學和企業級應用。與Python相比,PHP在web開發中更具優勢,但在數據科學領域不如Python;與Java相比,PHP在企業級應用中表現較差,但在web開發中更靈活;與JavaScript相比,PHP在後端開發中更簡潔,但在前端開發中不如JavaScript。

PHP和Python各有優勢,適合不同場景。 1.PHP適用於web開發,提供內置web服務器和豐富函數庫。 2.Python適合數據科學和機器學習,語法簡潔且有強大標準庫。選擇時應根據項目需求決定。

PHPhassignificantlyimpactedwebdevelopmentandextendsbeyondit.1)ItpowersmajorplatformslikeWordPressandexcelsindatabaseinteractions.2)PHP'sadaptabilityallowsittoscaleforlargeapplicationsusingframeworkslikeLaravel.3)Beyondweb,PHPisusedincommand-linescrip

PHP成為許多網站首選技術棧的原因包括其易用性、強大社區支持和廣泛應用。 1)易於學習和使用,適合初學者。 2)擁有龐大的開發者社區,資源豐富。 3)廣泛應用於WordPress、Drupal等平台。 4)與Web服務器緊密集成,簡化開發部署。

PHP適用於Web開發和內容管理系統,Python適合數據科學、機器學習和自動化腳本。 1.PHP在構建快速、可擴展的網站和應用程序方面表現出色,常用於WordPress等CMS。 2.Python在數據科學和機器學習領域表現卓越,擁有豐富的庫如NumPy和TensorFlow。
