【发布时间】:2014-07-30 16:02:29
【问题描述】:
我知道我应该使 Public Class 不可变,但我仍然在将 Person 对象添加到类型为 HashSet 的 Set 集合之前更改了它的名称,并且我的 Person 类还实现了 hashCode() 和等于() 方法有助于检查对象是否与前一个对象相同,并在 hashCode() 和 equals() 方法的帮助下防止添加到列表中,但输出仍然是:
鲍勃
查理
鲍勃
而不是: 鲍勃 查理
如果我替换主类的代码段:
Set<Person> set = new HashSet<Person>();
Person a= new Person("alice",45);
Person b=new Person("bob",41);
Person c= new Person("charlie",48);
set.add(a);
a.name="bob";
set.add(b);
set.add(c);
通过下面的代码(即我直接声明了一个等效对象,而不像原来的有问题的代码那样稍后更改名称):
Set<Person> set = new HashSet<Person>();
Person a= new Person("bob",45);
Person b=new Person("bob",41);
Person c= new Person("charlie",48);
set.add(a);
set.add(b);
set.add(c);
那么对象b就不加了。
还有一点需要注意的是,我在添加对象 b 之前更改了对象的名称(在原始有问题的代码中)a 但仍然添加 b 为什么????
下面详细给出了包含主类和公共类的原始问题代码::
//Main.java class of generics_practice_test package;
package generics_practice_test;
import java.util.Set;
import java.util.HashSet;
import java.util.Iterator;
public class Main {
public static void main (String args[])
{
Set<Person> set = new HashSet<Person>();
Person a= new Person("alice",45);
Person b=new Person("bob",41);
Person c= new Person("charlie",48);
set.add(a);
a.name="bob";
set.add(b);
set.add(c);
for(Iterator<Person> iterator=set.iterator();iterator.hasNext();){
System.out.println(iterator.next());
}
}
}
Person 类的代码如下: //generics_practice_test包的Person类如下
package generics_practice_test;
public class Person implements Comparable<Person> {
public String name;
public int age;
public Person(String name,int age)
{
this.name=name;
this.age=age;
}
public String toString()
{
return this.name;
}
public int compareTo(Person o)
{
int myLength=name.length();
int oLength=o.name.length();
if(myLength == oLength) return 0;
if(oLength > myLength) return -1;
return 1;
}
@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;
Person other = (Person) obj;
if (name == null) {
if (other.name != null)
return false;
} else if (!name.equals(other.name))
return false;
return true;
}
}
【问题讨论】:
-
b仍添加在a.name="bob"之后,因为a与其旧哈希一起存储。更改a.name会更改a.hashCode()返回值,但包含HashSet无法知道这一点——因此a仍使用其旧哈希(与b.hashCode()不同)保存在存储中跨度> -
谢谢 blgt 先生,它帮助了。