【问题标题】:Java HashSet contains ObjectJava HashSet 包含对象
【发布时间】:2015-01-30 00:44:42
【问题描述】:

我使用重写的 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()
  • 我知道,但这不是我的问题。
  • 这听起来更像是一个糟糕的设计,需要解决,而不是具体的实现。
  • 那么,您对这两种方法都有覆盖,但它仍然不起作用? “这样的对象”是什么意思?你有一些你正在寻找的实际对象吗?
  • @stonar96 那么你的问题不清楚。请更新它以包含已覆盖 hashCode 的事实。但在这种情况下,contains 应该会找到您的对象。还请提供任何相关代码和数据,以便我们重现您的问题。

标签: java object equals contains hashset


【解决方案1】:

您还必须重写 hashCode 方法。

【讨论】:

    【解决方案2】:

    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.
    

    【讨论】:

    • 我有另一个参考,我想检查它是否仍在列表中。你知道我的意思吗?
    【解决方案3】:

    在您的情况下,判断对象的特定实例是否包含在 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;
    }
    

    【讨论】:

      【解决方案4】:

      检查对象是否为同一对象的方法是将它们与 == 进行比较,以查看对象引用是否相等。

      亲切的问候, 弗兰克

      【讨论】:

      • 谢谢,您的回答就是我的问题的回答。
      【解决方案5】:

      试试这个.. 仅考虑对象的一个​​属性“名称”以保持唯一性。

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

      【讨论】:

        【解决方案6】:

        我使用重写的 equals 方法创建了自己的类,该方法只检查名称(类中的属性)是否相等。

        这违反了.equals 的约定,无论看起来多么方便,都绝对不能这样做。

        相反,如果您想通过某个属性(例如名称)来索引和查找元素,请使用HashMap&lt;Name, YourType&gt; 来查找它们。或者,使用 TreeSet 并将其传递给仅比较名称的 Comparator。然后您可以删除不正确的equals 方法。

        如果你想通过引用相等来查找对象,那么有三种方法:

        1. 您的对象没有固有的或有用的平等概念。

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

        2. 您的对象确实有一个有用的、普遍的相等概念,但无论如何您都希望有效地找到等效的实例。

          几乎从来没有这种情况。但是,您可以使用例如一个阿帕奇IdentityMap

        3. 你不关心效率。

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

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2011-07-03
          • 2013-05-15
          • 2011-10-24
          • 2023-01-17
          相关资源
          最近更新 更多