为什么Set允许重复?

时间:2015-08-30 02:21:54

标签: java set hashset

我有以下代码:

class Animal {
    int i;

    public Animal(){
        i=13;
    }

    public String toString(){
        return "Animal "+i;
    }
}
//
public class NewMain {
    public static void main(String[] args) {
        HashSet hs=new HashSet();
        boolean b=hs.add(new Animal());
        boolean b1=hs.add(new Animal());
        System.out.println(b+" "+b1);
        for(Object o:hs)
        {
            System.out.println(hs);
        }
    }
}

我知道Set不允许重复,但为什么上面的代码似乎允许两个相同的值?

3 个答案:

答案 0 :(得分:7)

因为Java无法知道您的两个实例是相同的。

您需要覆盖equals() hashcode()

答案 1 :(得分:6)

正如已经指出的那样,您需要覆盖hashCodeequals。您可以在int i上比较类似的内容,

class Animal {
    int i;

    public Animal() {
        i = 13;
    }

    @Override
    public String toString() {
        return "Animal " + i;
    }

    @Override
    public int hashCode() {
        return Integer.hashCode(i);
    }

    @Override
    public boolean equals(Object obj) {
        if (obj instanceof Animal) {
            return ((Animal) obj).i == i;
        }
        return false;
    }
}

然后我建议您在Collection使用泛型。此外,您应该在循环中打印实例(而不是Collection)。像,

public static void main(String[] args) {
    Set<Animal> hs = new HashSet<>();
    boolean b = hs.add(new Animal());
    boolean b1 = hs.add(new Animal());
    System.out.println(b + " " + b1);
    for (Animal a : hs) {
        System.out.println(a);
    }
}

我得到了(预期的)

true false
Animal 13

答案 2 :(得分:4)

您尚未在hashcode课程中覆盖equalsAnimal。因此,这些方法继承自java.lang.Object

继承的行为(来自Object)是对象只有在相同的对象时才相等。

在这种情况下,equalshashcode的一对合适的覆盖将是这样的:

  @Override
  public boolean equals(Object other) {
      return other instanceof Animal && 
             other != null &&
             ((Animal) other).i == this.i;
  }

  @Override
  public int hashCode() {
      return i;
  }

(请注意,如果您开始创建Animal的子类,则需要仔细考虑如何最好地实施equals(Object)。通过以上代码,我们不会尝试处理... )