91超碰碰碰碰久久久久久综合_超碰av人澡人澡人澡人澡人掠_国产黄大片在线观看画质优化_txt小说免费全本

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

Java怎么根據key值修改Hashmap中的value值

發布時間:2023-05-06 11:40:48 來源:億速云 閱讀:116 作者:iii 欄目:開發技術

這篇文章主要講解了“Java怎么根據key值修改Hashmap中的value值”,文中的講解內容簡單清晰,易于學習與理解,下面請大家跟著小編的思路慢慢深入,一起來研究和學習“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值”的內容了,經過本文的學習后,相信大家對Java怎么根據key值修改Hashmap中的value值這一問題有了更深刻的體會,具體使用情況還需要大家實踐驗證。這里是億速云,小編將為大家推送更多相關知識點的文章,歡迎關注!

    向AI問一下細節

    免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

    AI

    双桥区| 舒兰市| 德惠市| 武清区| 文成县| 稷山县| 龙胜| 茶陵县| 开化县| 延川县| 治县。| 北辰区| 古田县| 广元市| 凉山| 乌拉特前旗| 遵化市| 德庆县| 西充县| 林芝县| 西盟| 东乌| 东海县| 托克托县| 齐齐哈尔市| 城口县| 洛阳市| 北海市| 开化县| 新巴尔虎右旗| 吉安县| 右玉县| 庄浪县| 阳信县| 衡水市| 水城县| 兰西县| 浪卡子县| 横峰县| 九寨沟县| 大同县|