【问题标题】:ArrayList's custom Contains methodArrayList 的自定义 Contains 方法
【发布时间】:2012-01-09 11:07:46
【问题描述】:

我有一些东西

class A {
  private Long id; 
  private String name; 
  public boolean equals(Long v) {
     return this.id.equals(v);
  }
}

和这些对象的 ArrayList。 我想要的是能够通过对象的字段检查该列表是否包含某些对象。 例如:

ArrayList<A> list = new ArrayList<A>(); if (list.contains(0L)) {...}

但重写的 Equals 方法对我没有帮助。我做错了什么? 谢谢

更新 我也应该重写 hashcode() 方法吗?

【问题讨论】:

  • 你在你的 A 类中重写了 equals() 吗?如果是的话,你能把它贴在这里吗?
  • 从下面的答案来看,我想没有方便的解决方案。我觉得这可以通过匿名类实现来解决,就像您使用自己的 Comparator 调用 Collections.sort() 时使用的那种。
  • 经过一番搜索,我在这里找到了一些有用的答案:stackoverflow.com/questions/587404/…

标签: java arraylist contains


【解决方案1】:

你没有覆盖你的类中的方法。为了覆盖,方法参数也必须是相同的类型。

应该是

public boolean equals(Object o) {

}

在你的情况下它在哪里

public boolean equals(Long o) {

 }

你可能需要这样做

public boolean equals(Object o)
    {
        if (o == null) return false;
        if (o == this) return true; //if both pointing towards same object on heap

            A a = (A) o;
        return this.id.equals(a.id);
    }

【讨论】:

  • 我更新了代码,结果还是一样。包含找不到具有特定 ID 的对象
  • 查看我的答案以获得可能的解释 - “另一个问题......”
  • 我认为在演员表之前添加一个 if 是个好主意... if(!(o instanceof A)) return false;
【解决方案2】:

我做错了什么?

你没有压倒一切。你超载了。

contains 方法调用带有签名equals(Object)equals 方法,因此您添加的这个(新)方法将不会被调用。

另一个问题是您的equals 方法对contains 有错误的语义。 contains 方法需要将 this 与可能是列表成员的对象进行比较。您的列表不包含 Long 对象。它包含A 类型的对象。

现在您可能会侥幸逃脱...如果您使用原始列表类型...但是您尝试做的是违反 API 合同和不良做法。更好的解决方案是显式地迭代和测试列表的元素。


我也应该重写 hashcode() 方法吗?

如果你覆盖equals(Object),那么你也应该覆盖hashcode()

在这里不会有任何区别,但是如果您将A 对象放入散列数据结构中,这将是必不可少的。而且,由于您不知道下一个人会对您的代码做什么,因此最好确保 equals(Object)hashCode() 具有兼容的语义。

【讨论】:

    【解决方案3】:

    这里有一些代码可以演示它是如何工作的:

    import java.util.ArrayList;
    
    class A {
      private Long id; 
      private String name; 
    
      A(Long id){
          this.id = id;
      }
    
        @Override
      public boolean equals(Object v) {
            boolean retVal = false;
    
            if (v instanceof A){
                A ptr = (A) v;
                retVal = ptr.id.longValue() == this.id;
            }
    
         return retVal;
      }
    
        @Override
        public int hashCode() {
            int hash = 7;
            hash = 17 * hash + (this.id != null ? this.id.hashCode() : 0);
            return hash;
        }
    }
    
    public class ArrayList_recap {
        public static void main(String[] args) {
            ArrayList<A> list = new ArrayList<A>(); 
    
            list.add(new A(0L));
            list.add(new A(1L));
    
            if (list.contains(new A(0L)))
            {
                System.out.println("Equal");
            }
            else
            {
                System.out.println("Nah.");
            }    
        }
    
    }
    

    首先,有一个对 equals(Object o) 方法的覆盖。然后还有 hashCode() 的覆盖。另请注意,在 equals 中的 instanceof A 检查将确保您不会尝试比较不同的对象。

    这应该可以解决问题!希望它有所帮助!干杯:)

    【讨论】:

    • 很好的例子谢谢!
    • @Vern 嗨,我试图实现和你一样的东西,就我而言,我有一个 POJO 类,我试图使用 contains 方法比较一个属性,但它没有按预期工作。如果您有 id 的 setter 和 getter 并命名您将传递给 contains 方法的值,能否请您告诉我。
    • 我有两个要使用的属性。我将如何实施hashCode() 方法?
    猜你喜欢
    • 2017-11-16
    • 2019-02-18
    • 2014-08-20
    • 2015-06-17
    • 2013-07-06
    • 1970-01-01
    • 2012-11-01
    • 2021-02-01
    相关资源
    最近更新 更多