目次
キーの値に応じてハッシュマップの値を変更します
HashMapのキーを変更した後、値は正しく取得できますか?
テスト ケース
つまり、
ホームページ Java &#&チュートリアル Javaのキー値に基づいてハッシュマップの値を変更する方法

Javaのキー値に基づいてハッシュマップの値を変更する方法

May 13, 2023 pm 02:25 PM
java hashmap key

    キーの値に応じてハッシュマップの値を変更します

    元のマップにキーがない場合は作成されます。元のマップのキーの場合、元の値は value で上書きされます。

    map.put(key,value);
    ログイン後にコピー

    の値は、元の値に 1 を加算します (このキーがある場合)

    map.put(key,map.get(key)+1);
    ログイン後にコピー

    対応する値キーへの値は次のように取得できますが、そうでない場合はデフォルト値を返すことができます

    map.getOrDefault(key,value);
    ログイン後にコピー

    HashMapのキーを変更した後、値は正しく取得できますか?

    HashMap に格納される一連のキーと値のペア。キーはカスタム タイプです。 HashMapに入れた後、外部からあるキーの属性を変更し、そのキーを使ってHashMapから要素を取り出すのですが、このときHashMapは何を返すのでしょうか?

    社内の数人の回答はバラバラで、nullが返されるという人もいれば、普通に値が返せるという人もいます。しかし、答えが何であれ、明確な理由はありません。この質問は非常に興味深いと思ったので、コードテストを書きました。結果はヌルです。カスタム クラスは hashCode メソッドをオーバーライドすることに注意してください。この結果は少し予想外だと思います。HashMap には参照型が格納されていることがわかっていて、外側のキーを更新しました。つまり、HashMap 内のキーも更新され、このキーの hashCode 戻り値も更新されることになります。 。 バラエティ。このとき、keyとHashMapのhashCodeは要素のhashCodeと同じである必要があり、同じオブジェクトなのでequalsは必ずtrueを返すはずですが、なぜ正しい値を返せないのでしょうか?

    テスト ケース

    ここには 2 つのケースがあり、1 つは person クラス、もう 1 つは Student クラスです。上記の観点を (結論とともに) 検証してみましょう:

    • オブジェクトのプロパティを変更するとハッシュコードが変更されるかどうか => はい

    • 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
    学生
    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&#39;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&#39;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;
    }
    ログイン後にコピー

    つまり、

    最初にテーブルが取得され、このテーブルが実際には配列であることがわかります。次に、テーブル内のキーに対応する値を見つけます。検索の基準は、ハッシュが渡されたパラメータのハッシュと等しく、他の 2 つの条件のいずれかを満たしていることです: k = e.key。これは、それらが同じオブジェクトであるか、等しいターゲットのキーであることを意味します。渡されたキーの。問題は hash(key.hashCode()) にあります。HashMap が要素を格納するときにキーの hashCode をハッシュしていることがわかります。取得されたハッシュは、最終的に要素の保存場所の基礎として使用されます。今回の状況に対応すると、初めて保存するとき、ハッシュ関数は key.hashCode をパラメーターとして使用して値を取得し、この値に基づいて要素を特定の場所に保存します。

    要素を再度取得すると、key.hashCode の値が変更されているため、ここでのハッシュ関数の結果も変更されているため、このキーの格納場所を取得しようとすると、正しい値を取得できません。値が不足しているため、ターゲット要素が見つかりません。正しく返すには、非常に簡単です。変更したい属性にその hashCode が依存しないように、Person クラスの hashCode メソッドを変更します。ただし、これは実際の開発では行うべきではありません。 2 つのオブジェクトの属性は異なりますが、まったく同じである場合は、異なる hashCode 値が返されることがあります。

    結論としては、オブジェクトを HashMap に配置した後は、属性の制限を受けないエンティティ クラスの hashCode メソッドをオーバーライドしない限り、キーの属性を変更しないでください。

    以上がJavaのキー値に基づいてハッシュマップの値を変更する方法の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

    このウェブサイトの声明
    この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。

    ホットAIツール

    Undresser.AI Undress

    Undresser.AI Undress

    リアルなヌード写真を作成する AI 搭載アプリ

    AI Clothes Remover

    AI Clothes Remover

    写真から衣服を削除するオンライン AI ツール。

    Undress AI Tool

    Undress AI Tool

    脱衣画像を無料で

    Clothoff.io

    Clothoff.io

    AI衣類リムーバー

    AI Hentai Generator

    AI Hentai Generator

    AIヘンタイを無料で生成します。

    ホットツール

    メモ帳++7.3.1

    メモ帳++7.3.1

    使いやすく無料のコードエディター

    SublimeText3 中国語版

    SublimeText3 中国語版

    中国語版、とても使いやすい

    ゼンドスタジオ 13.0.1

    ゼンドスタジオ 13.0.1

    強力な PHP 統合開発環境

    ドリームウィーバー CS6

    ドリームウィーバー CS6

    ビジュアル Web 開発ツール

    SublimeText3 Mac版

    SublimeText3 Mac版

    神レベルのコード編集ソフト(SublimeText3)

    Javaの平方根 Javaの平方根 Aug 30, 2024 pm 04:26 PM

    Java の平方根のガイド。ここでは、Java で平方根がどのように機能するかを、例とそのコード実装をそれぞれ示して説明します。

    Javaの完全数 Javaの完全数 Aug 30, 2024 pm 04:28 PM

    Java における完全数のガイド。ここでは、定義、Java で完全数を確認する方法、コード実装の例について説明します。

    Java の乱数ジェネレーター Java の乱数ジェネレーター Aug 30, 2024 pm 04:27 PM

    Java の乱数ジェネレーターのガイド。ここでは、Java の関数について例を挙げて説明し、2 つの異なるジェネレーターについて例を挙げて説明します。

    ジャワのウェカ ジャワのウェカ Aug 30, 2024 pm 04:28 PM

    Java の Weka へのガイド。ここでは、weka java の概要、使い方、プラットフォームの種類、利点について例を交えて説明します。

    Javaのアームストロング数 Javaのアームストロング数 Aug 30, 2024 pm 04:26 PM

    Java のアームストロング番号に関するガイド。ここでは、Java でのアームストロング数の概要とコードの一部について説明します。

    Javaのスミス番号 Javaのスミス番号 Aug 30, 2024 pm 04:28 PM

    Java のスミス番号のガイド。ここでは定義、Java でスミス番号を確認する方法について説明します。コード実装の例。

    パッチ不可能な Yubico 2 要素認証キーの脆弱性により、ほとんどの Yubikey 5、セキュリティ キー、YubiHSM 2FA デバイスのセキュリティが侵害される パッチ不可能な Yubico 2 要素認証キーの脆弱性により、ほとんどの Yubikey 5、セキュリティ キー、YubiHSM 2FA デバイスのセキュリティが侵害される Sep 04, 2024 pm 06:32 PM

    パッチ不可能な Yubico の 2 要素認証キーの脆弱性により、ほとんどの Yubikey 5、セキュリティ キー、および YubiHSM 2FA デバイスのセキュリティが破られています。 Feitian A22 JavaCard および Infineon SLB96xx シリーズ TPM を使用するその他のデバイスも脆弱です。すべて

    Java Springのインタビューの質問 Java Springのインタビューの質問 Aug 30, 2024 pm 04:29 PM

    この記事では、Java Spring の面接で最もよく聞かれる質問とその詳細な回答をまとめました。面接を突破できるように。

    See all articles