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

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

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

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

如果原來(lái)map中沒(méi)有key,會(huì)創(chuàng)建,如果原來(lái)有key,會(huì)使用value 覆蓋掉原來(lái)的值

map.put(key,value);

這個(gè)實(shí)現(xiàn)對(duì)原值加一(前提是有這個(gè)key)

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

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

map.getOrDefault(key,value);

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

在HashMap 中存放的一系列鍵值對(duì),其中鍵為某個(gè)我們自定義的類型。放入 HashMap 后,我們?cè)谕獠堪涯骋粋€(gè) key 的屬性進(jìn)行更改,然后我們?cè)儆眠@個(gè) key 從 HashMap 里取出元素,這時(shí)候 HashMap 會(huì)返回什么?

我們辦公室?guī)讉€(gè)人答案都不一致,有的說(shuō)返回null,有的說(shuō)能正常返回value。但不論答案是什么都沒(méi)有確鑿的理由。我覺(jué)得這個(gè)問(wèn)題挺有意思的,就寫了代碼測(cè)試。結(jié)果是返回null。需要說(shuō)明的是我們自定義的類重寫了 hashCode 方法。我想這個(gè)結(jié)果還是有點(diǎn)意外的,因?yàn)槲覀冎?HashMap 存放的是引用類型,我們?cè)谕饷姘?key 更新了,那也就是說(shuō) HashMap 里面的 key 也更新了,也就是這個(gè) key 的 hashCode 返回值也會(huì)發(fā)生變化。這個(gè)時(shí)候 key 的 hashCode 和 HashMap 對(duì)于元素的 hashCode 肯定一樣,equals也肯定返回true,因?yàn)楸緛?lái)就是同一個(gè)對(duì)象,那為什么不能返回正確的值呢?

測(cè)試案例

這里有 2 個(gè)案例,一個(gè)是 Person 類,還有一個(gè)是 Student 類,我們來(lái)驗(yàn)證下以上的觀點(diǎn)(附帶結(jié)論):

  • 修改了對(duì)象屬性是否會(huì)改變它的 hashcode => 是的
  • 在 HashMap 里存取的時(shí)候是否會(huì)受到修改屬性影響取值 => 取值為 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;
}

總之

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

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

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

最后

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

相關(guān)文章

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

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

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

    如何獲取Maven項(xiàng)目的版本號(hào)

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

    zookeeper watch機(jī)制的理解

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

    java連接ElasticSearch集群操作

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

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

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

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

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

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

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

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

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

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

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

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

    下面小編就為大家?guī)?lái)一篇SpringMVC的REST風(fēng)格的四種請(qǐng)求方式總結(jié)。小編覺(jué)得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧
    2017-08-08

最新評(píng)論

北辰区| 宾川县| 且末县| 保定市| 南平市| 米泉市| 高雄县| 靖安县| 农安县| 太康县| 武山县| 泗洪县| 屯昌县| 房山区| 尼勒克县| 三门县| 湛江市| 南投市| 阿克陶县| 哈密市| 新绛县| 扶沟县| 巴林右旗| 和平县| 江津市| 虞城县| 鹤岗市| 铜陵市| 若羌县| 昌乐县| 鄂托克前旗| 南丰县| 沧源| 广河县| 石屏县| 吕梁市| 通江县| 义马市| 武夷山市| 亳州市| 阳西县|