簡體   English   中英

hashcode如何存儲值

[英]How hashcode stores values

我上課了

public class Customer {

    private int customerId;
    private String customerName;
    private String customerType;
    private String customerAddress;

    public Customer(int customerId, String customerName, String customerType, String customerAddress) {
        super();
        this.customerId = customerId;
        this.customerName = customerName;
        this.customerType = customerType;
        this.customerAddress = customerAddress;
    }

    public int getCustomerId() {
        return customerId;
    }

    public void setCustomerId(int customerId) {
        this.customerId = customerId;
    }

    public String getCustomerName() {
        return customerName;
    }

    public void setCustomerName(String customerName) {
        this.customerName = customerName;
    }

    public String getCustomerType() {
        return customerType;
    }

    public void setCustomerType(String customerType) {
        this.customerType = customerType;
    }

    public String getCustomerAddress() {
        return customerAddress;
    }

    public void setCustomerAddress(String customerAddress) {
        this.customerAddress = customerAddress;
    }

    @Override
    public String toString() {
        return "Customer [customerId=" + customerId + ", customerName=" + customerName + ", customerType="
                + customerType + ", customerAddress=" + customerAddress + "]";
    }

    @Override
    public int hashCode() {
        final int prime = 31;
        int result = 1;
        result = prime * result + ((customerAddress == null) ? 0 : customerAddress.hashCode());
        result = prime * result + ((customerName == null) ? 0 : customerName.hashCode());
        result = prime * result + ((customerType == null) ? 0 : customerType.hashCode());
        return result;
    }

    @Override
    public boolean equals(Object obj) {
        if (this == obj)
            return true;
        if (obj == null)
            return false;
        if (getClass() != obj.getClass())
            return false;
        Customer other = (Customer) obj;
        if (customerAddress == null) {
            if (other.customerAddress != null)
                return false;
        } else if (!customerAddress.equals(other.customerAddress))
            return false;
        if (customerName == null) {
            if (other.customerName != null)
                return false;
        } else if (!customerName.equals(other.customerName))
            return false;
        if (customerType == null) {
            if (other.customerType != null)
                return false;
        } else if (!customerType.equals(other.customerType))
            return false;
        return true;
    }

}

請注意,我已從等於和哈希碼計算中刪除了customerId。 我創建此方法以使用客戶對象作為鍵

public static Map<Customer, String> testKeysWithObject(){
    Map<Customer, String> map = new HashMap<>();

    Customer customer1 = new Customer(1, "customerName1", "customerType1", "customerAddress1");
    Customer customer2 = new Customer(2, "customerName2", "customerType2", "customerAddress2");
    Customer customer3 = new Customer(3, "customerName3", "customerType3", "customerAddress3");
    Customer customer4 = new Customer(4, "customerName4", "customerType4", "customerAddress4");


    map.put(customer1, "customer1");
    map.put(customer2, "customer2");
    map.put(customer3, "customer3");
    map.put(customer4, "customer4");

    customer4 = new Customer(5, "customerName5", "customerType5", "customerAddress5");

    customer3.setCustomerAddress("customerAddress5");
    System.out.println(customer4.getCustomerAddress());
    return map;
}

以下方法遍歷Hashmap。

public static void displayMap(Map<Customer, String> map) {
    System.out.println("==================================  ENTRY SET  ==========================================");
    for (Entry<Customer, String> mapKeys : map.entrySet()) {
        if(null != mapKeys)
            System.out.println("Key -> " + mapKeys.getKey() + " Value -> " + mapKeys.getValue()+ " HashCode -> " + mapKeys.hashCode());
    }
    System.out.println();
    System.out.println("==================================  KEY SET  ==========================================");
    for (Customer mapKeys : map.keySet()) {
        if(null != map.get(mapKeys))
            System.out.println("Key -> " + mapKeys + " Value -> " + map.get(mapKeys) + " HashCode -> " + map.get(mapKeys).hashCode());
    }
}

以下是輸出。

 customerAddress5 

================================== ENTRY SET ============== ============================密鑰 - >客戶[customerId = 3,customerName = customerName3,
customerType = customerType3,customerAddress = customerAddress5]值 - > customer3 HashCode - > 291012570密鑰 - >客戶[customerId = 4,customerName = customerName4,customerType = customerType4,customerAddress = customerAddress4]值 - > customer4 HashCode - > 291011640密鑰 - >客戶[ customerId = 2,customerName = customerName2,customerType = customerType2,customerAddress = customerAddress2] Value - > customer2 HashCode - > 291210360 Key - > Customer [customerId = 1,customerName = customerName1,customerType = customerType1,customerAddress = customerAddress1] Value - > customer1 HashCode - > 291211416

================================== KEY SET ============== ============================密鑰 - >客戶[customerId = 4,customerName = customerName4,
customerType = customerType4,customerAddress = customerAddress4] Value - > customer4 HashCode - > 1611562006 Key - > Customer [customerId = 2,customerName = customerName2,customerType = customerType2,customerAddress = customerAddress2] Value - > customer2 HashCode - > 1611562004 Key - > Customer [ customerId = 1,customerName = customerName1,customerType = customerType1,customerAddress = customerAddress1] Value - > customer1 HashCode - > 1611562003

我對這個hashmap行為有幾個問題

  1. 為什么hashmap不受customer4 = new assignment的影響,hashcode如何存儲這些。
  2. hashMap如何影響customer3.setCustomerAddress(“customerAddress5”);
  3. 為什么keyset()和entryset方法返回了兩個不同的值。
  4. hashmap是否存儲實際對象的引用,如果引用則為什么customer4 = new對hashmap沒有影響?

為什么hashmap不受customer4 = new assignment的影響,hashcode如何存儲這些。

您正在為customer4變量分配新對象,您不會更改對象本身。 Map保存對舊對象的引用,並且不知道您已更改customer4

hashMap如何影響customer3.setCustomerAddress(“customerAddress5”);

您正在更改對象本身。 地圖中的customer3和customer都指向同一個對象。

為什么keyset()和entryset方法返回了兩個不同的值。

永遠不要將可變對象作為鍵。 或者至少在放入地圖后不要改變它們。 地圖無法處理此更改,無法重新排序條目。 這就是"customerAddres5"的密鑰被“遺漏”的原因。

我可以看到更改反映在entryset()而不是keyset()中,這讓我想知道hashmap如何能夠用一種方法而不是另一種方法來應對更改。

entrySet方法返回帶有(key - > value)對的整個集合。 你檢查null != mapKeys在這里是多余的,因為它們都不是空的並且它們已經相互連接。

keySet方法僅返回鍵。 它還返回4個項目,但您要過濾掉帶有"customerAddress5"條目,因為您試圖通過此鍵獲取值。 但是,由於您更改了address字段並且映射無法檢索此鍵的值,因此該密鑰的哈希碼已更改。

結論: 永遠不要改變關鍵狀態。 讓它變得一成不變,所以沒人能改變它。

hashmap是否存儲實際對象的引用,如果引用則為什么customer4 = new對hashmap沒有影響?

您正在重新分配customer4 再次閱讀第一個問題的答案。

您必須了解的是,您的四個Customer變量中的每一個都只是對某個Object的引用。 當你調用map.put(customer4, "customer4"); ,你要說'使用變量customer4引用的對象作為值“customer4”'的鍵。 當您使用new語句重新分配customer4時,不會修改Object,而是更改customer4 ,以便它不再引用該第一個Object。

至於你的第二個問題, customer3同樣是對變量的引用。 在指定customer3以引用new Object之后,將該Object放入HashMap 現在有兩個對這個對象的引用; 其中一個是customer3 ,另一個是HashMap的條目。 當您調用setCustomerAddress() ,您現在正在對該Object進行操作,因此從這兩個參考點可以看到更改。

至於為什么keyset()和entryset()方法返回不同的hashCode ,在你的第一個循環中, mapKeysEntry類型,而在第二個循環中, map.get(mapKeys)String類型,所以它們自然會產生不同的hashCode

最后,Java中的所有內容都是參考。 當您put customer4放入Map時,您實際上是在引用Object。 當您重新分配customer4時,您只是將變量指向另一個Object,但該引用的另一個副本並沒有消失。 因此,更改變量customer4不會影響Map中的條目。

  1. 在這里,您將customer4指向另一個對象。因此,HashMap不會受到影響。 對第4個問題的回答是一樣的。

  2. 所有這些都是因為您的Customer對象是Mutable。 你可以參考這個這個知道為什么HashMap的鍵應該是一成不變的。

  3. 這是因為您已通過customer3.setCustomerAddress更改了Customer對象。 檢索Keyset()時,將返回所有鍵。 但是當您嘗試使用該密鑰檢索值時,它現在將指向另一個桶(請記住,您已使用客戶地址來計算哈希碼)。

暫無
暫無

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

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