Почему HashMap переопределяет существующий объект, когда я получаю разные хэш-коды для одного и того же объекта? - PullRequest
0 голосов
/ 31 октября 2019
import java.util.HashMap;
import java.util.Map; 

class Geek  
{ 

    public String name; 
    public int id; 

    Geek(String name, int id)  
    { 

        this.name = name; 
        this.id = id; 
    } 

    @Override
    public boolean equals(Object obj) 
    { 

    // checking if both the object references are  
    // referring to the same object. 
    if(this == obj) 
            return true; 

        // it checks if the argument is of the  
        // type Geek by comparing the classes  
        // of the passed argument and this object. 
        // if(!(obj instanceof Geek)) return false; ---> avoid. 
        if(obj == null || obj.getClass()!= this.getClass()) 
            return false; 

        // type casting of the argument.  
        Geek geek = (Geek) obj; 

        // comparing the state of argument with  
        // the state of 'this' Object. 
        System.out.println("equals method ....."+(geek.name == this.name && geek.id == this.id));
        return (geek.name == this.name && geek.id == this.id); 
    } 

    int counter = 0;

    @Override
    public int hashCode() 
    { 

        // We are returning the Geek_id  
        // as a hashcode value. 
        // we can also return some  
        // other calculated value or may 
        // be memory address of the  
        // Object on which it is invoked.  
        // it depends on how you implement  
        // hashCode() method. 
        ++counter;
        System.out.println("counter ::>>> "+counter);
        return counter;
    } 

Код драйвера:

public static void main (String[] args) 
{ 

    Map<Geek, Integer> map = new HashMap<>();

    // creating the Objects of Geek class. 
    Geek g1 = new Geek("aa", 1); 
    Geek g2 = new Geek("aa", 1); 


    map.put(g1, g1.id);
    map.put(g2, g2.id);

    map.forEach((k,v) -> {
        System.out.println("key = "+k + "\n value = "+v);
    });

   /* else
    System.out.println("Both Objects are not equal. ");  */
}

Здесь я переопределяю метод hashCode(), но карта все еще содержит только один объект g2. Почему HashMap не хранит два объекта, учитывая, что мой хэш-код каждый раз возвращает разные целые числа?

Даже если мой метод equals() возвращает true для одного и того же объекта, почему HashMap не хранит два объекта? Может ли кто-нибудь, пожалуйста, направить меня в этом отношении?

Ответы [ 2 ]

7 голосов
/ 31 октября 2019

Ваша переменная counter является переменной экземпляра, поэтому она инициализируется значением 0 для каждого экземпляра Geek. Следовательно, и g1, и g2 имеют одинаковые hashCode() из 1, когда вы помещаете их в Map, и считаются идентичными HashMap, поскольку они равны друг другу на основе вашегоequals реализация.

Если вы измените counter на static, вы получите разные hashCode() для 2 экземпляров Geek, и они будут сохранены в отдельных записях карты.

Тем не менее, ваша реализация hashCode() очень плохая. Если вы звоните hashCode() для одного и того же экземпляра несколько раз, вы будете каждый раз получать другой результат! Это означает, что если вы попытаетесь поместить g1 дважды в Map, он, вероятно, поместит его дважды, поскольку второй put увидит другое hashCode() и, следовательно, будет искать ключ в другом ведре. .

1 голос
/ 31 октября 2019

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

Согласно Object.hashCode() javadoc :

Всякий раз, когда он вызывается для одного и того же объекта более одного раза во время выполнения приложения Java, метод hashCode должен последовательно возвращать одно и то же целое число при условии, что никакая информация, используемая в сравнениях сравнения для объекта, не изменяется. Это целое число не должно оставаться согласованным при выполнении одного приложения другим исполнением того же приложения.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...