为什么 Set 在这里允许重复?
Why does Set allow a duplicate here?
我有以下代码:
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
不允许重复,但为什么上面的代码似乎允许两个相同的值?
因为Java无法知道你的两个实例是一样的。
您需要覆盖 equals()
和 hashcode()
.
您尚未覆盖 Animal
class 中的 hashcode
和 equals
。因此,这些方法都是继承自java.lang.Object
.
继承的行为(来自 Object
)是对象只有在它们是同一对象时才相等。
在这种情况下,equals
和 hashcode
的一对合适的覆盖应该是这样的:
@Override
public boolean equals(Object other) {
return other instanceof Animal &&
other != null &&
((Animal) other).i == this.i;
}
@Override
public int hashCode() {
return i;
}
(请注意,如果您开始创建 Animal
的子 class,您需要仔细考虑如何最好地实现 equals(Object)
。上面的代码不会尝试处理那个...)
如前所述,您需要覆盖 hashCode
和 equals
。您可以将 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
我有以下代码:
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
不允许重复,但为什么上面的代码似乎允许两个相同的值?
因为Java无法知道你的两个实例是一样的。
您需要覆盖 equals()
和 hashcode()
.
您尚未覆盖 Animal
class 中的 hashcode
和 equals
。因此,这些方法都是继承自java.lang.Object
.
继承的行为(来自 Object
)是对象只有在它们是同一对象时才相等。
在这种情况下,equals
和 hashcode
的一对合适的覆盖应该是这样的:
@Override
public boolean equals(Object other) {
return other instanceof Animal &&
other != null &&
((Animal) other).i == this.i;
}
@Override
public int hashCode() {
return i;
}
(请注意,如果您开始创建 Animal
的子 class,您需要仔细考虑如何最好地实现 equals(Object)
。上面的代码不会尝试处理那个...)
如前所述,您需要覆盖 hashCode
和 equals
。您可以将 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