Как написать метод hashCode для определенного класса?

Я пытаюсь создать метод hashCode() для моего простого класса, но я не получаю нигде с ним. Буду признателен за любую помощь. Я реализовал метод equals(), который выглядит следующим образом, а также хотел бы знать, нужно ли мне реализовать метод compareTo(). Я импортировал java.lang.Character для использования character.hashCode(), но он, похоже, не работает.

private class Coord{
    private char row;
    private char col;
    public Coord(char x, char y){
        row = x;
        col = y;
    }
    public Coord(){};

    public char getX(){
        return row;
    }

    public char getY(){
        return col;
    }

    public boolean equals(Object copy){
        if(copy == null){
            throw new NullPointerException("Object entered is empty");
        }
        else if(copy.getClass()!=this.getClass()){
            throw new IllegalArgumentException("Object entered is not Coord");
        }
        else{
            Coord copy2 = (Coord)copy;
            if(copy2.row==this.row && copy2.col==this.col)
                return true;
            else
                return false;
        }
    }

}

Спасибо заранее...

Метод ComparTo(), который дает мне java.lang.Comparable ошибку кастинга.

public int compareTo(Object copy){
        if(copy==null){
            throw new NullPointerException("Object entered is empty");
        }
        else if(copy.getClass()!=this.getClass()){
            throw new IllegalArgumentException("Object entered is not Coord");
        }
        else{
            Coord copy2 = (Coord)copy;
            if(copy2.row==this.row && copy2.col==this.col){
                return 0;
            }
            else if(copy2.col < this.col){
                return -1;
            }
            else{
                return 1;
            }
        }
    }

спасибо...

Ответы

Ответ 1

Для реализации hashCode вы переопределяете реализацию по умолчанию из Object:

@Override
public int hashCode()
{
    return row ^ col;
}

Это не идеальный хеш, так как его результаты очень предсказуемы, и для двух разных объектов Coord легко вернуть одно и то же значение. Лучший хэш использовал бы встроенный класс Arrays из java.util (http://docs.oracle.com/javase/7/docs/api/java/util/Arrays.html):

@Override
public int hashCode()
{
    return Arrays.hashCode(new Object[]{new Character(row), new Character(col)});
}

Вы можете использовать этот метод для создания довольно хорошего хэша с любым количеством полей.

Для реализации compareTo вы хотите, чтобы ваш класс реализовал Comparable:

public class Coord implements Comparable<Coord>

Как только вы это сделаете, вы можете сделать compareTo взять аргумент типа Coord, а не тип Object, что избавит вас от необходимости проверять его тип.

Ответ 2

Hashcode - это int (32 бит), ваши данные char (16 бит), поэтому я бы просто сделал:

@Override
public int hashCode() {
    return (row << 16) + col;
}

Это ставит биты из row в первые 16 бит и бит из col в последние 16 бит, поэтому это perfect хэш-функции для этого класса.

Если вы реорганизуете свой класс, чтобы быть более сложным, я рекомендую использовать ответ nullptr.


Чтобы использовать Comparable, выполните:

public class Coord implements Comparable<Coord>

Ответ 3

Я нашел очень ценную информацию по этой теме и многим другим темам в Эффективной Java-книге, написанной Джошуа Блохом. Посмотрите на стр. 45 для получения дополнительной информации о hashCode() и equals().

Если вы используете IDE, например Eclipse, вы можете позволить ему генерировать методы hashCode() и equals(). Для вашего класса результатом будет:

class Coord implements Comparable<Coord> {

    private char row;
    private char col;

    public Coord(char x, char y) {
        row = x;
        col = y;
    }

    public Coord() {
    };

    public char getX() {
        return row;
    }

    public char getY() {
        return col;
    }

    @Override
    public int hashCode() {
        final int prime = 31;
        int result = 1;
        result = prime * result + col;
        result = prime * result + row;
        return result;
    }

    @Override
    public boolean equals(Object obj) {
        if (this == obj)
            return true;
        if (obj == null)
            return false;
        if (getClass() != obj.getClass())
            return false;
        Coord other = (Coord) obj;
        if (col != other.col)
            return false;
        if (row != other.row)
            return false;
        return true;
    }

    public int compareTo(Coord param) {
        // Implementation according to http://docs.oracle.com/javase/7/docs/api/java/lang/Comparable.html
        return 0;
    }

}

Ответ 4

похож на ответ durron597, вы можете попробовать это, если ваш вход ограничен char (между 0 и 65535)

public int hashCode(){
   return row * 100000 + col;
}