Переопределение hashCode в Java возвращает ноль при использовании hashmap и получении вновь созданных объектов - PullRequest
1 голос
/ 23 октября 2019

В настоящее время я изучаю хэш-код Java через MOOC и следую их руководству. Однако ожидаемый результат возвращает ноль, когда внутри hashmap явно есть значение. Мой код для переопределения следующий:


public class Plate{
    private final String regCode;
    private final String country;

    // Counstructors
    ...

    // accessors... only showing name for less clutter
    getCode() 
    getCountry()

    @Override // toString
    public String toString(){
        return country + " " + regCode;
    }

    @Override // equals
    public boolean equals(Object obj){
        if(obj == null){
            return false;
        }   

        if(getClass() != obj.getClass()){
            return false;
        }

        Plate cmp = (Plate) obj;

        if(this.country.equals(cmp.getCountry())){
            return false;
        }

        if(this.regCode == null || this.regCode.equals(cmp.getCode())){
            return false;
        }

        return true;
    }

///////////////////////////////////// Below code may be the problem ///////////////////////////////////
    @Override // hashCode 
    public int hashCode(){
        if(this.country == null || this.regCode == null){
            return 7;
        }   

        return this.country.hashCode() + this.regCode.hashCode(); 

    }
}

и моя основная функция, которая использует вышеуказанный код:

import java.util.ArrayList;
import java.util.HashMap;

public class Regi{
    public static void main(String[] args){
        Plate reg1 = new Plate("FI", "ABC-123");
        Plate reg2 = new Plate("FI", "UXE-465");
        Plate reg3 = new Plate("D", "B WQ-431");

        ArrayList<Plate> finnish = new ArrayList<Plate>();
        finnish.add(reg1);
        finnish.add(reg2);

        Plate newPlate = new Plate("FI", "ABC-123");
        if(!finnish.contains(newPlate)){
            finnish.add(newPlate);
        }
        System.out.println("Finnish " + finnish);


// where unexpected result occur
        HashMap<Plate, String> owners = new HashMap<Plate, String>();
        owners.put(reg1, "Arto");
        owners.put(reg3, "Jurgen");

        System.out.println("Owners:");
        System.out.println(owners.get(reg1));
        System.out.println(owners.get(new Plate("FI", "ABC-123")));
        System.out.println(owners.get(new Plate("D", "B WQ-431")));

    }
}

Где ожидаемый результат:

enter image description here

, но мой вывод отображает null ниже «владельцев:» порцию, когда я запускаю System.out.println(owners.get(new Plate("FI", "ABC-123"))); и System.out.println(owners.get(new Plate("D", "B WQ-431")));. Я не уверен, что не так с моей пользовательской функцией hashCode, так как я смог распечатать оба моих hashCode для country и regCode, и они оба дали числовые значения. Я также ссылался на чей-то пост, касающийся хэш-кода для использования простого числа, но он по-прежнему отображал ноль. Мне было интересно, если кто-нибудь может указать мне правильное направление относительно hashCode.

1 Ответ

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

Ваш код не работает, потому что вы заставляете equals возвращать false, когда два объекта имеют одинаковое country. Или тот же regCode:

if(this.country.equals(cmp.getCountry())){
    return false;
}

if(this.regCode == null || this.regCode.equals(cmp.getCode())){
    return false;
}

Вам не хватает оператора ! (НЕ):

if (! this.country.equals(cmp.getCountry())) {
    return false;
}

if (this.regCode == null || ! this.regCode.equals(cmp.getCode())) {
    return false;
}

Кроме того, ваш hashCode()реализация подразумевает, что country может быть null, поэтому вы пропускаете нулевую проверку:

if (this.country == null || ! this.country.equals(cmp.getCountry())) {
    return false;
}
...