簡體   English   中英

我們可以使用 object 作為 Java 中 hashmap 中的鍵嗎?

[英]Can we use object as a key in hashmap in Java?

如何使用 object 作為 hashmap 中的密鑰。 如果您使用 object 作為鍵,您是否需要覆蓋該 object 的等於和哈希碼方法?

一個簡單的經驗法則是使用不可變對象作為HashMap

因為:

如果它是可變的,那么hashcode()值或equals()條件可能會更改,並且您將永遠無法從HashMap檢索鍵。

更准確地說,用於計算equals()hashcode()類字段應該是不可變的!

現在,假設您創建了自己的類:

  • 要比較類的兩個對象,您必須覆蓋equals()
  • 要將其用作任何基於 Hash 的數據結構中的鍵,您必須覆蓋hashcode() (再次,牢記不變性)

請記住,如果兩個對象是equal() ,那么它們的hashcode()應該相等!

hashCode() -HashMap 提供用於存儲的 put(key, value) 和用於從 HashMap 檢索值的 get(key) 方法。 當 put() 方法用於存儲 (Key, Value) 對時,HashMap 實現調用 Key 對象上的 hashcode 來計算用於查找存儲 Entry 對象的存儲桶的哈希值。 當 get() 方法用於檢索值時,再次使用鍵對象來計算哈希,然后使用該哈希來查找存儲該特定鍵的存儲桶。

equals() - equals() 方法用於比較對象的相等性。 如果使用 HashMap 鍵對象進行比較,同樣使用 equals() 方法 Map 知道如何處理散列沖突(散列沖突意味着多個鍵具有相同的散列值,因此分配到同一個桶。在這種情況下,對象是存儲在鏈表中,請參閱圖以獲得更清晰的信息。其中 hashCode 方法有助於找到存儲該鍵的存儲桶,equals 方法有助於找到正確的鍵,因為單個存儲桶中可能存儲了多個鍵值對.

您可以在HashMap使用任何對象,只要它具有正確定義的hashCodeequals方法——這些絕對是至關重要的,因為散列機制取決於它們。

是的,您應該覆蓋 equals 和 hashcode,以便代碼正常運行,否則您將無法獲得已插入地圖的鍵的值。

例如

map.put(new Object() , "value") ;

當你想獲得那個價值時,

map.get(new Object()) ; // 這將始終返回 null

因為使用 new Object() - 將生成新的哈希碼並且它不會指向保存值的預期桶號,並且如果最終桶號變得相同 - 它將無法匹配哈希碼甚至等於所以它總是返回 NULL 。

您的問題的答案是肯定的,自定義類的對象可以用作 HashMap 中的鍵。 但是為了不失敗地從映射中取回值對象,需要遵循某些准則。

1)Custom class should follow the between hashCode() and equals(). 1)Custom class should follow the約定between hashCode() and equals().

合同規定:

If two objects are equal according to the equals(Object) method, then calling
the hashCode method on each of the two objects must produce the same integer result.

這可以通過在自定義類中實現 hashcode() 和 equals() 來完成。

2) Make custom class immutable.

提示:使用final,刪除setter,使用deep copy來設置字段

Yes, we can use any object as key in a Map in java but we need to override the equals() and hashCode() methods of that object class. 請參考下面的示例,其中我將一對 class 的 object 存儲為 hashMap 中的鍵,其值類型為 Z9018DC81AE51244B 中的字符串。 我已經覆蓋了 Pair class 的 hashCode() 和 equals() 方法。 因此,具有相同 Pair(x,y) 值的 Pair class 的不同對象將僅被視為一個 object。

import java.util.*;
import java.util.Map.Entry;

class App { // Case-sensitive
    private class Pair {
        private int x, y;

        public Pair(int x, int y) {
            this.x = x;
            this.y = y;
        }

        @Override
        public int hashCode() {
            final int prime = 31;
            int result = 1;
            result = prime * result + x;
            result = prime * result + y;
            return result;
        }

        @Override
        public boolean equals(Object obj) {
            if (this == obj)
                return true;
            if (obj == null)
                return false;
            if (getClass() != obj.getClass())
                return false;
            Pair other = (Pair) obj;

            if (x != other.x)
                return false;
            if (y != other.y)
                return false;
            return true;
        }

    }

    public static void main(String[] args) {
        App obj = new App();
        obj.show();
    }

    private void show() {
        Map<Pair, String> map = new HashMap<>();
        Pair obj1 = new Pair(10, 20);
        Pair obj2 = new Pair(40, 50);
        Pair obj3 = new Pair(10, 20);
        // We can see that obj1 and obj3 have same values. So, we want to store these
        // objects
        // as one .To achieve
        // that,
        // we have overridden equals() and hashCode() methods of Pair class.

        map.put(obj1, "First");
        map.put(obj2, "Second");
        map.put(obj3, "Third");
        System.out.printf("Size of Map is :%d \n", map.size());

        for (Entry<App.Pair, String> p : map.entrySet()) {
            Pair pair = p.getKey();
            System.out.printf("Map key-value pair is (%d,%d)->%s \n", pair.x, pair.y, p.getValue());
        }
        // output -
        // Size of Map is :2
        // Map key-value pair is (10,20)->Third
        // Map key-value pair is (40,50)->Second
    }

}
package com.java.demo.map;

import java.util.HashMap;

public class TestMutableKey
{
    public static void main(String[] args)
    {
        //Create a HashMap with mutable key
        HashMap<Account, String> map = new HashMap<Account, String>();

        //Create key 1
        Account a1 = new Account(1);
        a1.setHolderName("A_ONE");
        //Create key 2
        Account a2 = new Account(2);
        a2.setHolderName("A_TWO");

        //Put mutable key and value in map
        map.put(a1, a1.getHolderName());
        map.put(a2, a2.getHolderName());

        //Change the keys state so hash map should be calculated again
        a1.setHolderName("Defaulter");
        a2.setHolderName("Bankrupt");

        //Success !! We are able to get back the values
        System.out.println(map.get(a1)); //Prints A_ONE
        System.out.println(map.get(a2)); //Prints A_TWO

        //Try with newly created key with same account number
        Account a3 = new Account(1);
        a3.setHolderName("A_THREE");

        //Success !! We are still able to get back the value for account number 1
        System.out.println(map.get(a3)); //Prints A_ONE
    }
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM