2017-01-12 2 views
-1

У меня есть HashSet Whare я буду хранить набор для объектов, и я хочу, чтобы найти конкретный объект, в данном случае, почему мне нужно сделать, чтобы переопределить хэш-код и составляет метод, который я читал снизу, напримерКогда мне нужен метод hashcode и equals?

public class Emp 
{ 
    private int age ; 

    public Emp(int age) 
    { 
     super(); 
     this.age = age; 
    } 

    public int hashCode() 
    { 
     return age; 
    } 

    public boolean equals(Object obj) 
    { 
     boolean flag = false; 
     Emp emp = (Emp)obj; 
     if(emp.age == age) 
      flag = true; 
     return flag; 
    } 
} 

Они говорят я бы получил false для нижеприведенного запроса, если я не переопределяю метод hashcode и equals.

System.out.println("HashSet Size--->>>"+hs.size()); 
System.out.println("hs.contains(new Emp(25))--->>>"+hs.contains(new Emp(25))); 
System.out.println("hs.remove(new Emp(24)--->>>"+hs.remove(new Emp(24)); 
System.out.println("Now HashSet Size--->>>"+hs.size()); 

меня запутать, как это связано с Hashcode и равна просто проверяя содержит (anyobject) и удалить (anyobject) в HashSet.

Может ли кто-нибудь объяснить мне приведенный выше сценарий?

+3

Возможный дубликат: https://stackoverflow.com/questions/2265503/why-do-i-need-to-override-the-equals-and-hashcode-methods-in-java?rq=1 –

+0

Вы спрашивая, почему вам нужно переопределить любой из них, или почему вам нужно переопределить их оба? Если последнее: http://stackoverflow.com/questions/2265503/why-do-i-need-to-override-the-equals-and-hashcode-methods-in-java – yshavit

+1

Как контейнер должен знать, если он содержит что-то, если он не может определить, равны ли какие-либо две вещи или нет? Точно так же, как это должно знать, если все равно, если вы не говорите, как это сделать? – azurefrog

ответ

4

В основе вашего замешательства лежит концепция идентичности против равенства, а что означает, что для набора должен содержать элемент. Позвольте мне попытаться объяснить.

Пусть в каком-то месте в своем коде вы сделали это:

HashSet<Emp> hs = new HashSet<>(); 
hs.add(new Emp(32)); 

В каком-то другом месте, вы хотите увидеть, является ли работник в возрасте 32 лет находится в наборе. Как бы вы это сделали? Вы можете считать это:

boolean isThere = hs.contains(new Emp(32)); 

, что вы делаете здесь создается экземпляр Emp прохождения 32 конструктору, а затем передавая экземпляр contain().

Обратите внимание, что этот экземпляр не совпадает с экземпляром, созданным при добавлении в набор. Итак, вопрос: должен ли вернуть true, так как этот экземпляр идентичен тому, который вы добавили, или ему нужно вернуть false, так как это не тот самый экземпляр?

Результат зависит от того, как hashCode() и equals() для Emp. При реализации по умолчанию equals() возвращает true, только если переданный экземпляр является тем же самым, что содержится (например, использует == для сравнения экземпляра, прошедшего с , и тот, который хранится). В этом случае он вернет false.

Чтобы понять hashCode(), вам нужно понять, как работает HashSet. Когда вы добавляете элемент в HashSet, индекс в массиве вычисляется из элемента с помощью hashCode() % <size of the array>. Затем элемент устанавливается как значение в соответствующем индексе.

Поскольку различные элементы могут иметь одинаковые hashCode(), большее количество элементов может отображаться с одним и тем же индексом, и в этом случае сохраняется список столкновений.

Итак, вернемся к вашему делу, зачем вам нужно использовать hashCode()? потому что реализация по умолчанию возвращает разные числа для разных экземпляров Ent, событие, хотя age может быть одинаковым (реализация зависит от JVM, например, она может вернуть адрес в память экземпляра). Таким образом, для того, чтобы скомпоновать работу, нам нужно убедиться, что один и тот же индекс в массиве вычисляется для двух экземпляров, поэтому вам необходимо его реализовать соответствующим образом. например, в этом случае hashCode() может вернуть сам возраст.

Смежные вопросы