java - 比较 HashSet 中的对象
问题描述
我正在制作一个包含星星的 2D 游戏。我决定在名为 Star 的类中创建构造函数,它给出随机坐标。
public Star(){
super(0,0);
x = randomX.nextInt(maxX - minX + 1);
y = randomY.nextInt(maxX - minY + 1);
}
然后,在其他课程中,我将它们放入 HashSet
Set<Star> star = new HashSet<>();
public Set<Star> generateStars(){
while (star.size() < numberOfStars){
star.add(new Star());
}
return star;
}
当然,我有 render 和 tick 方法,但我认为不值得粘贴它们。我的讲师告诉我,可以有相同的星星,为了防止我应该使用使用哈希码的身份函数。有人可以帮我弄清楚吗?我想这个函数应该检查哈希码是否相同,如果是这种情况,它应该只返回一个值,这样我们将在 HashSet 中添加 1 个对象而不是 2 个对象。我对吗 ?
解决方案
hashCode()
在您的类中单独覆盖该方法Star
将不起作用,您将不得不覆盖该equals()
方法。
请参阅以下代码,其中我们不覆盖该equals()
方法:
class Star {
int x, y;
public Star(int x, int y) {
this.x = x;
this.y = y;
}
@Override
public int hashCode() {
return Objects.hash(x, y);
}
}
public class Main {
public static void main(String[] args) {
Star s1 = new Star(0, 0);
Star s3 = new Star(0, 0);
Star s2 = new Star(31, -31*31);
Set<Star> set = new HashSet<>();
set.add(s1);
set.add(s2);
System.out.println(set.size());
}
}
这将打印 3(而不是您可能期望的 2)。
原因是 add 方法java.util.Set
基于equals()
方法而不是基于方法比较 2 个对象hashCode()
。
在上面的Star
类代码中,如果添加equals()
方法,现在输出将为 2。供您参考,您可以equals()
按如下方式覆盖该方法:
@Override
public boolean equals(Object startObject) {
if (this == startObject) return true;
if (startObject == null || getClass() != startObject.getClass()) return false;
Star star = (Star) startObject;
return x == star.x &&
y == star.y;
}
那么为什么需要添加hashCode()
呢?
- 当您
HashSet
在场景后面使用 add 方法时,将调用该equals()
方法并且还将调用hashCode()
以决定应该将新对象放入的存储桶。为了保持hashCode()
和equals()
两者的合同应该被覆盖。 - 每当您覆盖
equals()
时,建议也覆盖hashCode()
。(反之亦然)。有关详细信息,请参阅此链接。
hashCode()
and的契约equals()
:如果对于两个对象说o1
and o2
,o1.equals(o2)
那么和的true
哈希值是相同的。o1
o2
should
确保您正确理解这一点,从上面的陈述中并不暗示如果 2 个对象的哈希值相同,则o1.equals(o2)
应该返回true
。对于 2 个对象,它们的哈希值可能相同,但o1.equals(o2)
返回值可能相同false
看这里,什么Object
是hashCode()
方法保证。
请参阅此链接以获取有关此主题的更多详细信息。
推荐阅读
- java - 如何过滤具有子列表的父对象和具有孙子列表的子对象并通过匹配孙子的属性
- python - 在读取 csv 文件时向数据框添加一列 [pandas]
- r - 从 R 数据框中过滤掉时间数据
- sql - 以升序对 MMM-YYYY 文本数据进行排序的 SQL 查询
- c++ - 如何让 Chrome 开发工具显示 JavaScript 源代码
- java - 为什么@Secured 在 Tapestry 5.4.0 中不起作用?
- php - WooCommerce 中的产品存档描述,带有阅读更多标签
- c# - Async 有错误的返回类型
- java - 搜索视图打开时无法完全隐藏工具栏标题
- python - 从 gps 坐标列表中获取点之间的距离