【问题标题】:How to write hashCode method for a particular class?如何为特定类编写 hashCode 方法?
【发布时间】:2013-05-04 19:05:16
【问题描述】:

我正在尝试为我的简单类生成一个 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;
        }
    }

}

提前谢谢...

给我 java.lang.Comparable 转换错误的 comparTo() 方法..

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;
            }
        }
    }

谢谢...

【问题讨论】:

标签: java class character hashcode compareto


【解决方案1】:

要实现 hashCode,你需要覆盖 Object 的默认实现:

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

这并不是一个真正的理想哈希,因为它的结果是非常可预测的,并且两个不同的Coord 对象很容易返回相同的值。更好的哈希将利用来自 java.util (http://docs.oracle.com/javase/7/docs/api/java/util/Arrays.html) 的内置 Arrays 类:

@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 类型,这样可以省去检查其类型的麻烦。

【讨论】:

  • 如果您使用自 Java 1.5 以来一直在使用的 Arrays.hashCode(Object[] args),则不需要 Java 7
  • @durron597 我还编写了一个类似于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 &amp;&amp; copy2.col==this.col){ return 0; } else if(copy2.col &lt; this.col){ return -1; } else{ return 1; } } } 的comparTo() 方法,但我不断收到无法将Coord 强制转换为java.lang.Comparable。我可以知道为什么吗?
  • @AdityaGore 你应该在一个单独的问题中问这个问题。
  • @durron597 很抱歉。我已经编辑了我的问题并在此处添加了其他内容。我不知道是否建议针对类似问题发布两个不同的帖子!
  • 你说return row ^ col;“实际上并不是一个理想的哈希,因为......两个不同的Coord对象很容易返回相同的值。”我正在阅读article,它说:“hashCode 为对象提供唯一标识符是一种流行的误解。它没有。”你能详细说明一下这个问题吗?谢谢!
【解决方案2】:

哈希码是int(32 位),你的数据是char(16 位),所以我可能会这样做:

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

这会将来自row 的位放在前16 位中,将来自col 的位放在最后16 位中,所以这是这个类的perfect hash function

如果您将类重构为更复杂,我建议使用 nullptr 的答案。


要使用Comparable,请执行以下操作:

public class Coord implements Comparable<Coord>

【讨论】:

  • 如果我错了,请原谅我,但你永远不会有碰撞;可能的对象似乎与可能的 hashCode 一对一地映射。这应该非常快,所以这是一个很棒的答案。
  • 是的。 “不太可能”是轻描淡写。这实际上是一对字符的完美哈希函数;当且仅当它们表示相等的值时,两个对象将具有相同的哈希码。
  • @CoryKendall 好吧,请记住,HashMaphashCode() 值上使用模数,它不包含 2^32 个可能的单元格。所以对于某些字符和模数以及HashMap 大小,它仍然会发生冲突。但是,我同意我可以更好地表达它:)
  • @CoryKendall 我把措辞改得更准确了;)
【解决方案3】:

我在Effective Java book, written by Joshua Bloch 中找到了有关此主题和许多其他主题的非常有价值的信息。有关 hashCode() 和 equals() 的更多信息,请参阅第 45 页。

如果您使用像 Eclipse 这样的 IDE,您可以让它生成 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;
    }

}

【讨论】:

  • 我知道这是一个非常典型的实现,但它有一些棘手的数字缺点。如果您只有两个要散列的组件(例如此处),并且它们都具有相同的值(不是不寻常的情况),则这等效于32*hash+offset,它的熵比您的源散列少 5 位。不理想。
【解决方案4】:

类似于 durron597 的回答,如果您的输入以 char 为界(介于 0 和 65535 之间),您可以尝试此操作

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

【讨论】:

  • 这个答案是多余的,虽然它是正确的,但它很棘手,因为它包含一个非显而易见的幻数,它只有在大于或等于 65536 时才有效
猜你喜欢
  • 2021-05-31
  • 1970-01-01
  • 2013-09-16
  • 2015-07-20
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多