簡體   English   中英

如果hashcode返回一個常量值,則在HashSet.contains()的情況下調用hashCode()和equals()的次數

[英]Number of calls of hashCode() and equals() in case of HashSet.contains() if hashcode returns a constant value

我已閱讀過Java文檔頁面,但我無法解釋為什么hashCode()equals()的調用數量會像這樣變化?

import java.util.HashSet;
import java.util.Iterator;
import java.util.Set;
public class NumberOfCalls {
    int field;

    public int getField() {
        return field;
    }

    public NumberOfCalls(int field) {
        this.field = field;
    }

    @Override
    public int hashCode() {
        System.out.println("In Hashcode method.");
        return 10;
    }

    @Override
    public boolean equals(Object obj) {
        System.out.println("In Equals Method");
        if (this == obj)
            return true;
        if (obj == null)
            return false;
        if (getClass() != obj.getClass())
            return false;
        NumberOfCalls other = (NumberOfCalls) obj;
        if (field != other.field)
            return false;
        return true;
    }

    public static void main(String[] args) {
        NumberOfCalls object1 = new NumberOfCalls(5);
        NumberOfCalls object2 = new NumberOfCalls(6);
        NumberOfCalls object3 = new NumberOfCalls(5);
        Set<NumberOfCalls> set = new HashSet<NumberOfCalls>();
        set.add(object1);
        set.add(object2);
        Iterator<NumberOfCalls> it = set.iterator();
        System.out.print("Size of set is : " + set.size()
            + "\nObject fields values present in set are : ");
        while (it.hasNext()) {
            System.out.print(it.next().getField() + "   ");
        }
        System.out.println("\n---------------------------------------------------");
        System.out.println("Now checking number of calls -- ");
        System.out.println("Object1 is present in set ? - " + set.contains(object1)+"\n");
        System.out.println("Object2 is present in set ? - " + set.contains(object2)+"\n");
        System.out.println("Object3 is present in set ? - " + set.contains(object3)+"\n");
    }
}

上面代碼的輸出是

在Hashcode方法中。
在Hashcode方法中。
在等於方法
套裝的大小是:2
集合中存在的對象字段值為:6 5

-------------------------------------------------- -
現在檢查通話次數 -
在Hashcode方法中。
在等於方法
對象1出現在集合中? - 是的

在Hashcode方法中。
對象2出現在集合中? - 是的

在Hashcode方法中。
在等於方法
在等於方法
對象3出現在集合中? - 是的

問題:

  1. 為什么hashCode()equals()object1但不是object2情況下調用一次hashCode()在這種情況下只調用hashCode() )?
  2. 為什么在object3情況下調用equals()兩次?

當您向Set添加元素時,它將存儲在Map內部,其中key是您傳入的對象,value設置為null 內部Map維護鏈表的數組(存儲桶)。 這些陣列也可稱為存儲桶。 使用hashCode()方法評估存儲桶的索引。

在您的情況下,因為hashCode()返回一個常量值,所以放入Set的所有值都將放在同一個桶中。 所以對於第一次調用set.add(object1)內部結構就是這樣的

bucket [object1 - > null]

由於每個存儲桶包含一個鏈表,因此存儲在列表中的元素具有指向下一個元素的指針。 由於只有一個元素添加到列表中,因此指針指向null

對於下一次調用set.add(object2)數據結構將如下所示

bucket [object2 - > object1 - > null]

現在每當你調用set.contains(some_object) ,都會調用hashCode()來找出正確的存儲桶。 此調用還返回對第一個元素的引用。

回答第一個問題:

因此,當您調用set.contains(object2)它實際上返回對object2引用。 現在,如果查看HashMap類的代碼,它首先使用==運算符比較此引用是否與傳入的引用相同。 因為在這種情況下它是相同的所以它不會調用equals()方法。 以下是HashMap類的代碼片段:

if (e.hash == hash &&
                ((k = e.key) == key || (key != null && key.equals(k))))
                return e;

這應該解釋你的第一個問題。

回答第二個問題:

當您調用set.contains(object3) ,將計算存儲區索引並返回對object2引用。 現在object2 == object3返回false,因此Map調用object3.equals(object2)方法(首先調用equals()方法)來檢查兩個對象是否有意義相等。 這也返回false ,因此它遍歷list並返回對列表中下一個元素的引用,即object1

同樣, object1 == object3返回false,因此Map調用object3.equals(object1) (第二次調用equals()方法)方法來檢查兩個對象是否有意義相等。

這導致2次調用equals()方法。

暫無
暫無

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

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