最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

Java如何根據(jù)key值修改Hashmap中的value值

 更新時間:2023年03月22日 16:49:05   作者:學(xué)習(xí)路上的行人  
這篇文章主要介紹了Java如何根據(jù)key值修改Hashmap中的value值問題,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教

根據(jù)key值修改Hashmap的value值

如果原來map中沒有key,會創(chuàng)建,如果原來有key,會使用value 覆蓋掉原來的值

map.put(key,value);

這個實現(xiàn)對原值加一(前提是有這個key)

map.put(key,map.get(key)+1);

以下可以獲取key對應(yīng)的value,如果沒有可以返回默認(rèn)的value

map.getOrDefault(key,value);

HashMap的key更改后能否正確獲取value?

在HashMap 中存放的一系列鍵值對,其中鍵為某個我們自定義的類型。放入 HashMap 后,我們在外部把某一個 key 的屬性進(jìn)行更改,然后我們再用這個 key 從 HashMap 里取出元素,這時候 HashMap 會返回什么?

我們辦公室?guī)讉€人答案都不一致,有的說返回null,有的說能正常返回value。但不論答案是什么都沒有確鑿的理由。我覺得這個問題挺有意思的,就寫了代碼測試。結(jié)果是返回null。需要說明的是我們自定義的類重寫了 hashCode 方法。我想這個結(jié)果還是有點意外的,因為我們知道 HashMap 存放的是引用類型,我們在外面把 key 更新了,那也就是說 HashMap 里面的 key 也更新了,也就是這個 key 的 hashCode 返回值也會發(fā)生變化。這個時候 key 的 hashCode 和 HashMap 對于元素的 hashCode 肯定一樣,equals也肯定返回true,因為本來就是同一個對象,那為什么不能返回正確的值呢?

測試案例

這里有 2 個案例,一個是 Person 類,還有一個是 Student 類,我們來驗證下以上的觀點(附帶結(jié)論):

  • 修改了對象屬性是否會改變它的 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;
}

輸出結(jié)果

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實際上是個數(shù)組。然后在table里面找對應(yīng) key 的value。找的標(biāo)準(zhǔn)就是hash等于傳入?yún)?shù)的hash, 并且滿足另外兩個條件之一:k = e.key,也就是說他們是同一個對象,或者傳入的 key 的equal目標(biāo)的 key 。我們的問題出在那個hash(key.hashCode()),可以看到 HashMap 在存儲元素時是把 key 的 hashCode 再做了一次hash。得到的hash將最終作為元素存儲位置的依據(jù)。對應(yīng)到我們的情況:第一次存儲時,hash函數(shù)采用key.hashCode作為參數(shù)得到了一個值,然后根據(jù)這個值把元素存到了某個位置。

當(dāng)我們再去取元素的時候,key.hashCode的值已經(jīng)出現(xiàn)了變化,所以這里的hash函數(shù)結(jié)果也發(fā)生了變化,所以當(dāng)它嘗試去獲得這個 key 的存儲位置時就不能得到正確的值,導(dǎo)致最終找不到目標(biāo)元素。要想能正確返回,很簡單,把Person類的 hashCode 方法改一下,讓它的 hashCode 不依賴我們要修改的屬性,但實際開發(fā)中肯定不能這么干,我們總是希望當(dāng)兩個對象的屬性不完全相同時能返回不同的 hashCode 值。

所以結(jié)論就是當(dāng)把對象放到 HashMap 后,不要去修改 key 的屬性,除非你重寫了該實體類的 hashCode 方法不受屬性限制。

最后

以上為個人經(jīng)驗,希望能給大家一個參考,也希望大家多多支持腳本之家。

相關(guān)文章

  • 深入淺析Java中的final關(guān)鍵字

    深入淺析Java中的final關(guān)鍵字

    在Java中,final關(guān)鍵字可以用來修飾類、方法和變量(包括成員變量和局部變量),下面通過本篇文章給大家介紹java中的final關(guān)鍵字,對java fina關(guān)鍵字相關(guān)知識感興趣的朋友一起看看吧
    2015-12-12
  • 如何獲取Maven項目的版本號

    如何獲取Maven項目的版本號

    最近需要在項目中獲取項目的版本號,最笨的方法莫過于硬編碼一個版本號,當(dāng)然之前我也是這么干的。不過閑下來的時候突發(fā)奇想Spring Boot項目中pom.xml定義的版本號(也就是project.version的值)能不能通過API獲得呢?于是利用摸魚的時間研究了這種無聊透頂?shù)臇|西。
    2021-05-05
  • zookeeper watch機制的理解

    zookeeper watch機制的理解

    這篇文章主要介紹了zookeeper watch機制的相關(guān)內(nèi)容,內(nèi)容比較詳細(xì),需要的朋友可以參考下。
    2017-09-09
  • java連接ElasticSearch集群操作

    java連接ElasticSearch集群操作

    這篇文章主要介紹了java連接ElasticSearch集群操作,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2020-09-09
  • Spring MVC+mybatis實現(xiàn)注冊登錄功能

    Spring MVC+mybatis實現(xiàn)注冊登錄功能

    這篇文章主要為大家詳細(xì)介紹了Spring MVC+mybatis實現(xiàn)注冊登錄功能,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2017-07-07
  • java獲取圖片的大小、寬度、高度方式

    java獲取圖片的大小、寬度、高度方式

    文章介紹了如何將File對象轉(zhuǎn)換為MultipartFile對象的過程,并分享了個人經(jīng)驗,希望能為讀者提供參考
    2025-02-02
  • Java面向?qū)ο笾^承、構(gòu)造方法、重寫、重載

    Java面向?qū)ο笾^承、構(gòu)造方法、重寫、重載

    本章具體介紹了什么是構(gòu)造方法、繼承、重寫、重載以及創(chuàng)建方法,整篇文章用老司機和人類來舉例,圖解穿插代碼案例,需要的朋友可以參考下
    2023-03-03
  • Java面試題沖刺第十八天--Spring框架3

    Java面試題沖刺第十八天--Spring框架3

    這篇文章主要為大家分享了最有價值的三道關(guān)于Spring框架的面試題,涵蓋內(nèi)容全面,包括數(shù)據(jù)結(jié)構(gòu)和算法相關(guān)的題目、經(jīng)典面試編程題等,感興趣的小伙伴們可以參考一下
    2021-08-08
  • SkyWalking自定義鏈路追蹤實現(xiàn)步驟

    SkyWalking自定義鏈路追蹤實現(xiàn)步驟

    本文詳細(xì)介紹了如何使用SkyWalking進(jìn)行自定義鏈路追蹤的步驟,包括POM文件依賴和邏輯業(yè)務(wù)代碼的編寫,文章最后推薦了腳本之家作為進(jìn)一步學(xué)習(xí)的資源
    2024-02-02
  • SpringMVC的REST風(fēng)格的四種請求方式總結(jié)

    SpringMVC的REST風(fēng)格的四種請求方式總結(jié)

    下面小編就為大家?guī)硪黄猄pringMVC的REST風(fēng)格的四種請求方式總結(jié)。小編覺得挺不錯的,現(xiàn)在就分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2017-08-08

最新評論

忻州市| 沾化县| 长兴县| 乌海市| 临武县| 河池市| 汉川市| 贺州市| 海丰县| 齐河县| 寿宁县| 梁山县| 松原市| 佛学| 鄂尔多斯市| 林西县| 家居| 志丹县| 马尔康县| 德格县| 奉节县| 莱西市| 文成县| 商南县| 东阿县| 元朗区| 扎囊县| 甘南县| 康马县| 新河县| 新蔡县| 白银市| 桂东县| 伊宁县| 绥棱县| 宁陕县| 漯河市| 大英县| 历史| 叶城县| 杭锦旗|