Java HashSet包含Object吗?

3
我创建了一个自己的类,并覆盖了equals方法,该方法只检查名称(类中的属性)是否相等。现在,我将该类的一些实例存储在HashSet中,以便HashSet中没有具有相同名称的实例。
我的问题是:如何检查HashSet是否包含这样的对象。 .contains()在这种情况下不起作用,因为它使用.equals()方法。我想检查它是否真的是同一个对象。
编辑:
package testprogram;

import java.util.HashSet;
import java.util.Set;

public class Example {
    private static final Set<Example> set = new HashSet<Example>();
    private final String name;
    private int example;

    public Example(String name, int example) {
        this.name = name;
        this.example = example;
        set.add(this);
    }

    public boolean isThisInList() {
        return set.contains(this);
        //will return true if this is just equal to any instance in the list
        //but it should not
        //it should return true if the object is really in the list
    }

    public boolean remove() {
        return set.remove(this);
    }

    //Override equals and hashCode
}

抱歉,我的英语水平不是很好。如果您不理解我的意思,请随时再问。


当你重写 equals() 方法时,你必须同时重写 hashCode() 方法。 - Matt Ball
2
这听起来更像是需要解决的糟糕设计,而不是具体实现。 - Patrick J Abare II
@stonar96,你的问题不够清晰。请更新一下,说明你已经覆盖了 hashCode 方法。但是在这种情况下,contains 应该能够找到你的对象。请同时提供任何相关的代码和数据,以便我们可以重现你的问题。 - rgettman
如果你编写的 equals 太粗糙了,就将其变得更加精细。或者不覆盖 Object.equals - khelwood
这仍然不像是您想要的引用相等,而更像是在名称上使用Map。 - Louis Wasserman
显示剩余7条评论
6个回答

2

在您的情况下,唯一确定某个对象实例是否包含在HashSet中的方法是遍历HashSet的内容,并比较对象的身份(使用==运算符而不是equals()方法)。

可以尝试以下操作:

boolean isObjectInSet(Object object, Set<? extends Object> set) {
   boolean result = false;

   for(Object o : set) {
     if(o == object) {
       result = true;
       break;
     }
   }

   return result;
}

2

检查对象是否是同一对象的方法是通过使用“==”比较它们,以查看对象引用是否相等。

祝好, Frank


谢谢,你的回答就是我问题的答案。 - stonar96

1

试一下这个.. 只考虑你的对象的一个属性'名称'来维护唯一性。

@Override
public int hashCode() {
    final int prime = 31;
    int result = 1;
    result = prime * result + (name == null ? 0 : name.hashCode());
    return result;
}

@Override
public boolean equals(Object obj) {
    if (this == obj) {
        return true;
    }
    if (obj == null) {
        return false;
    }
    if (getClass() != obj.getClass()) {
        return false;
    }
    User other = (User) obj;
    if (name == null) {
        if (other.name != null) {
            return false;
        }
    } else if (!name.equals(other.name)) {
        return false;
    }
    return true;
}

0

HashSet contains 使用 equals 方法来确定对象是否被包含在其中 - 并且重复的元素不会在 HashSet 中保留。

假设您的equalshashcode仅使用一个name字段...

HashSet<MyObject> objectSet = new HashSet<MyObject>();
MyObject name1Object = new MyObject("name1");

objectSet.add(new MyObject("name1"));
objectSet.add(name1Object);
objectSet.add(new MyObject("name2"));
//HashSet now contains 2 objects, name1Object and the new name2 object
//HashSets do not hold duplicate objects (name1Object and the new object with name1 would be considered duplicates)

objectSet.contains(new MyObject("name1")) // returns true
objectSet.contains(name1Object)           // returns true
objectSet.contains(new MyObject("name2")) // returns true
objectSet.contains(new MyObject("name3")) // returns false

如果您想检查 HashSet 中的对象是否与您正在比较的确切对象相同,则必须将其取出并直接使用 == 进行比较。

for (MyObject o : objectSet)
{
    if (o == name1Object)
    {
        return true;
    }
}

如果你经常为特定对象执行此操作,使用 HashMap 可能更容易,因为你不必遍历列表来获取特定命名的对象。这可能值得你去研究一下,因为你可以像这样做:

(objectMap.get("name") == myNameObject) // with a HashMap<String, MyNameObject> where "name" is the key string.

我有另一个引用,我想检查它是否仍在列表中。你知道我的意思吗? - stonar96

0

你还需要重写hashCode方法。


0
我创建了一个自己的类,并覆盖了equals方法,该方法只检查类中的属性名称是否相等。
这违反了.equals的契约,无论看起来多么方便,您都不应该这样做。
相反,如果您想通过某个属性(例如名称)对元素进行索引和查找,请使用HashMap来查找它们。或者,使用TreeSet并传递一个仅比较名称的Comparator。然后,您可以删除不正确的equals方法。
如果您想通过引用相等性查找对象,则有三种方法:
  1. 你的对象没有内在或有用的相等概念。

    不要实现 equals。让它保持默认状态。然后,您可以使用 HashSet 查找引用相等性,并使用 HashMap 或 TreeSet 按任何特定属性对其进行索引。

  2. 你的对象确实具有有用的、普遍的相等概念,但你仍然希望有效地找到等效实例。

    这几乎从不发生。但是,您可以使用例如 Apache IdentityMap

  3. 你不关心效率。

    使用 for 循环和 == 每个元素。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接