当前位置: 首页 > 知识库问答 >
问题:

Java覆盖两个可互换整数的equals()和hashcode()

方绪
2023-03-14

我正在覆盖两个int的简单容器对象的equals和hashcode方法。每个int反映另一个对象的索引(该对象是什么并不重要)。该类的目的是表示两个对象之间的连接。

连接的方向无关紧要,因此equals方法应该返回true,无论两个整数在对象中以何种方式循环。

connectionA = new Connection(1,2);
connectionB = new Connection(1,3);
connectionC = new Connection(2,1);

connectionA.equals(connectionB); // returns false
connectionA.equals(connectionC); // returns true

这是我所拥有的(从整数的源代码修改):

public class Connection {
    // Simple container for two numbers which are connected.
    // Two Connection objects are equal regardless of the order of from and to.

    int from;
    int to;

    public Connection(int from, int to) {
        this.from = from;
        this.to = to;
    }

    // Modifed from Integer source code
    @Override
    public boolean equals(Object obj) {
        if (obj instanceof Connection) {
            Connection connectionObj = (Connection) obj;
            return ((from == connectionObj.from && to == connectionObj.to) || (from == connectionObj.to && to == connectionObj.from));
        }
        return false;
    }

    @Override
    public int hashCode() {
        return from*to;
    }
}

但我的问题是:有没有更好的方法来实现这一点?

我主要担心的是hashcode()方法会为任何两个相乘等于相同数字的整数返回相同的hashcode。例如。

3*4 = 12
2*6 = 12 // same!

文件,http://docs.oracle.com/javase/1.5.0/docs/api/java/lang/Object.html#hashCode()表示

如果根据equals(java.lang.Object)方法,两个对象是不等的,那么对这两个对象中的每一个调用hashCode方法都必须产生不同的整数结果,这不是必需的。然而,程序员应该知道,为不相等的对象生成不同的整数结果可能会提高哈希表的性能。

如果有人能找到一种简单的方法来减少匹配哈希码的数量,那么我将非常感谢你的回答。

谢啦!

提姆

附言:我知道有一个java.sql.连接可能会导致一些导入问题。该对象在我的应用程序中实际上有一个更具体的名称,但为了简洁起见,我在这里将其缩短为连接。

共有3个答案

房项禹
2023-03-14

我觉得

@Override
public int hashCode() {
    return to*to+from*from;
}

这就足够了

华君浩
2023-03-14

这是被广泛接受的方法:

@Override
public int hashCode() {
    int res = 17;
    res = res * 31 + Math.min(from, to);
    res = res * 31 + Math.max(from, to);
    return res;
}
司寇凯
2023-03-14

已经提出了三种“可行”的解决方案。(所谓工作,我的意思是它们满足哈希代码的基本要求……不同的输入产生不同的输出……而且它们还满足OP的额外“对称”要求。)

这些是:

   # 1
   return from ^ to;

   # 2
   return to*to+from*from;

   # 3
   int res = 17;
   res = res * 31 + Math.min(from, to);
   res = res * 31 + Math.max(from, to);
   return res;

第一个问题是,输出范围受到实际输入值范围的限制。例如,如果我们假设输入都是非负数,分别小于或等于2i和2j,那么输出将小于或等于2max(i,j)。这很可能会导致哈希表中的“分散度”很差。。。以及更高的碰撞率。(当from==to时也有问题!)

第二个和第三个要比第一个好,但是如果fromto较小,你仍然可能会遇到更多的碰撞。

如果将的较小值的冲突降至最低是至关重要的,我建议使用第四种选择。

  #4
  int res = Math.max(from, to);
  res = (res << 16) | (res >>> 16);  // exchange top and bottom 16 bits.
  res = res ^ Math.min(from, to);
  return res;

这样做的好处是,如果fromto都在0...216-1范围内,您将为每个不同的(无序)对获得唯一的哈希码。

1-我不知道这是否是正确的技术术语...

 类似资料:
  • 我试图覆盖提到的方法为我的: MyObject: 如何重写hashcode(),equals()和compareTo()方法? 目前我有以下几点: 我读到通过id比较是不够的,这是对象是数据库的持久实体(见这里)。 此类型的所有对象的名称和编号不是唯一的。 那么我应该如何覆盖它呢? 我还需要比较它里面的hashMap吗? 我很困惑。该对象唯一独特的地方是map myMap,它将在生命周期的后期填充

  • 问题内容: 今天,我遇到了一个有趣(非常令人沮丧)的方法问题,该问题导致我认为是一个经过良好测试的类崩溃了,并导致了一个错误,使我花了很长时间来追踪。 为了完整起见,我没有使用IDE或调试器-只是老式的文本编辑器和System.out。时间非常有限,这是一个学校项目。 无论如何- 我开发一个基本的购物车可能包含的Book对象。为了贯彻落实,以及对车的方法,我想检查,如果在已经存在。所以我走了 在测

  • 问题内容: 我试图覆盖Java中的方法。我有一堂课,基本上有2个数据字段和。现在,我想重写方法,以便可以在2个对象之间进行检查。 我的代码如下 但是当我写它给我错误时,因为方法只能比较并且是。 Solution 我按照建议使用运算符,问题解决了。 问题答案: Output: `run: – Subash Adhikari - VS - K false – Subash Adhikari - VS

  • 问题内容: 我对为什么Integer和int可以在Java中互换使用感到困惑,即使一个是原始类型,而另一个是对象也是如此? 例如: 要么 问题答案: 发布的文章的前几句话很好地描述了它: 您不能将int(或其他原始值)放入集合中。集合只能容纳对象引用,因此您必须将原始值装箱到适当的包装器类中(在int情况下为Integer)。当您从集合中取出对象时,您将得到放入的Integer。如果需要一个int

  • 问题内容: 在Java中重写equals方法以比较多个字段的最佳方法是什么?例如,我在类中有4个对象,分别为o1,o2,o3,o4,我想将所有这些对象与传递给equals方法的对象进行比较。 这段代码的问题在于它不清楚,如果我们有更多字段,就很难轻易修改。有没有更好的方法来实现这一目标? 问题答案: 一种便宜的方法是:

  • 问题内容: 在java中为什么需要覆盖equals和hashcode方法?什么时候用到? 问题答案: 让我们尝试通过一个示例来理解它,如果我们不进行覆盖而覆盖并尝试使用。 假设我们有一个类像这样那样的两个对象是相等的,如果他们等于(和生成) 仅覆盖 如果仅覆盖被覆盖,则在你第一次调用时将散列到某个存储桶,而在调用时将散列到其他存储桶(因为它们具有不同的)。因此,尽管它们是相等的,但由于它们没有散列