【问题标题】:Recognizing duplicates in HashSet识别 HashSet 中的重复项
【发布时间】:2014-01-20 15:03:44
【问题描述】:

所以,我用 Java 编写了这段代码:

import java.util.HashSet;

class Interval{
  long from;
  long to;

  public Interval(long from, long to) {
    this.from = from;
    this.to = to;
  }

  public boolean equals(Interval other) {

    return from == other.from && to == other.to;
  }


 }

public class Test {

   public static void main(String[] args) {

       HashSet<Interval> mySet  = new HashSet<Interval>();

       mySet.add(new Interval(1,2));
       mySet.add(new Interval(1,2));

       for(Interval in : mySet) {
        System.out.println(in.from + " " + in.to);
       }
   }

 }

问题是该集合无法识别已经存在从 1 到 2 的区间。我定义了函数 equals,但它仍然不起作用。我尝试实现 Comparable 接口并重载 compareTo 函数,但还是没有。有人可以告诉我如何解决这个问题吗?

谢谢!

【问题讨论】:

  • 在您的 Interval 类中覆盖并实现自定义 hashCode() 方法。
  • 你需要在你的类中重写equals和hashcode
  • 你的equals方法也应该是public boolean equals(Object some),否则,你重载它而不是@Overrideing它。
  • 您必须提供与您的平等定义相匹配的equals(Object)hashCode() 实现。
  • 这是equals(Object obj),而不是equals(Interval other)

标签: java object add hashset


【解决方案1】:

您需要从java.lang.Object 覆盖equals

你没有,因为你的不接受 Object 作为参数。

public boolean equals(Object obj) {
    if (obj == null)
        return false;
    else if (this.getClass() != obj.getClass())
        return false;
    else {
        Interval other = (Interval) obj;
        return from == other.from && to == other.to;
    }
}

例如,对于 hashCode,您可以这样做。

public int hashCode() {
    return new Long(this.from).hashCode();
}

所以总的来说你得到了这个代码。

import java.util.HashSet;

class Interval {
    long from;
    long to;

    public Interval(long from, long to) {
        this.from = from;
        this.to = to;
    }

    public boolean equals(Object obj) {
        if (obj == null)
            return false;
        else if (this.getClass() != obj.getClass())
            return false;
        else {
            Interval other = (Interval) obj;
            return from == other.from && to == other.to;
        }
    }

    public int hashCode() {
        return new Long(this.from).hashCode();
    }
}

public class Test003 {

    public static void main(String[] args) {

        HashSet<Interval> mySet = new HashSet<Interval>();

        mySet.add(new Interval(1, 2));
        mySet.add(new Interval2(1, 2));

        for (Interval in : mySet) {
            System.out.println(in.from + " " + in.to);
        }
    }

}

【讨论】:

  • 如果不覆盖 hashCode 仍然无法工作。
  • @NeplatnyUdaj 我知道。刚写完。
  • @Want :) NP,祝你好运。更多详情请点击此处:stackoverflow.com/questions/27581/…
  • @Want 我根据 Jaffar Ramay 的注释稍微更新了我的 equals 方法。
【解决方案2】:

使用下面这样的equals和hashCode方法就可以了

@Override
public int hashCode() {
    final int prime = 31;
    int result = 1;
    result = prime * result + (int) (from ^ from >>> 32);
    result = prime * result + (int) (to ^ to >>> 32);
    return result;
}

@Override
public boolean equals(Object obj) {
    if (this == obj) {
        return true;
    }
    if (obj == null) {
        return false;
    }
    if (getClass() != obj.getClass()) {
        return false;
    }
    Interval other = (Interval) obj;
    if (from != other.from) {
        return false;
    }
    if (to != other.to) {
        return false;
    }
    return true;
}

【讨论】:

  • 这不太对。 “getClass() != obj.getClass()” 想想如果你有 Inteval2 会发生什么,它扩展了 Interval 但什么都没有覆盖。 Interval(1,2) 和 Interval2(1,2) 将被检测为不相等,我猜这是不对的。
  • @peter.petrov 这两种方法都是由 Eclipse 生成的,而且完全没问题 :) Interval 和 IntervalChild 应该被视为 2 个不同的对象!!!
  • 好吧,这就是我写“我猜”的原因。虽然不确定这个 Interval 和 Interval2 的情况。如果 Eclipse 做到了,那么它可能是有意的。我没有使用 Eclipse 生成我的两个方法。
  • 用我刚刚从你那里学到的东西更新了我的 equals。希望它是正确的 :) 对我来说似乎是正确的,但仍然不是 100% 确定。我的意思是这部分:“Interval 和 Interval2 应该被视为 2 个不同的对象”。和我 +1。
猜你喜欢
  • 2015-03-31
  • 2015-10-18
  • 2011-11-16
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-04-06
  • 2018-07-04
相关资源
最近更新 更多