存储的数据类型是基本数据类型,可直接将list集合转换成set集合,或采用其他方法,上篇有陈述。本篇说下list集合中的数据类型是一个对象类型的情况,需要在对象的实体类中去重写equals()方法和hashCode()方法。
在该例中,我们将User实体类中用户编码和姓名作为判断该对象重复的标识,在User实体类中我们重写这两个方法如下:
public class User {
private int id;
private String userCd;
private String userNm;
private String phone;
private String memo;
public User(int id, String userCd, String userNm, String phone, String memo) {
super();
this.id = id;
this.userCd = userCd;
this.userNm = userNm;
this.phone = phone;
this.memo = memo;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getUserCd() {
return userCd;
}
public void setUserCd(String userCd) {
this.userCd = userCd;
}
public String getUserNm() {
return userNm;
}
public void setUserNm(String userNm) {
this.userNm = userNm;
}
public String getPhone() {
return phone;
}
public void setPhone(String phone) {
this.phone = phone;
}
public String getMemo() {
return memo;
}
public void setMemo(String memo) {
this.memo = memo;
}
@Override
public boolean equals(Object arg0) {
User u = (User) arg0;
return userCd.equals(u.userCd) && userNm.equals(u.userNm);
}
@Override
public int hashCode() {
String str = userCd + userNm;
return str.hashCode();
}
}
以上实体类中,我们在equals()方法中取出该对象的userCd和userNm这两个属性值去判断比较,然后在重写的hashCode()方法中返回这两个属性值得hashCode值。
package xuGroup.xuArtifact;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
public class Test2 {
public static void main(String[] args) {
// TODO Auto-generated method stub
List<User> userList = new ArrayList<User>();
userList.add(new User(1, "001", "张三", "13355556666", "前端"));
userList.add(new User(2, "002", "张三", "15522223333", "前端"));
userList.add(new User(3, "003", "李四", "13355556666", "后端"));
userList.add(new User(4, "004", "王五", "13311112222", "总监"));
userList.add(new User(5, "002", "张三", "13355556666", "设计"));
Set<User> setData = new HashSet<User>();
setData.addAll(userList);
System.out.println("list- size----" + userList.size());
System.out.println("list-----" + userList.toString());
System.out.println("set- size----" + setData.size());
System.out.println("set-----" + setData.toString());
for (User pp : setData) {
System.out.println("p--" + pp.toString());
}
}
}
一般情况下我们重写equals()方法的时候都要去重写hashCode()方法,
通过观察equals()方法的源码我们可以看出,该方法去比较两个对象时,首先先去判断两个对象是否具有相同的地址,如果是同一个对象的引用,则直接放回true;如果地址不一样,则证明不是引用同一个对象,接下来就是挨个去比较两个字符串对象的内容是否一致,完全相等返回true,否则false。
1. public boolean equals(Object anObject) {
2. if (this == anObject) {
3. return true;
4. }
5. if (anObject instanceof String) {
6. String anotherString = (String)anObject;
7. int n = count;
8. if (n == anotherString.count) {
9. char v1[] = value;
10. char v2[] = anotherString.value;
11. int i = offset;
12. int j = anotherString.offset;
13. while (n-- != 0) {
14. if (v1[i++] != v2[j++])
15. return false;
16. }
17. return true;
18. }
19. }
20. return false;
21. }
在Object类中的hashCode()方法是返回对象的32位JVM内存地址,也就是说如果我们不去重写该方法,将会返回该对象的32位JVM内存地址。
1. public int hashCode() {
2. int h = hash;
3. if (h == 0 && count > 0) {
4. int off = offset;
5. char val[] = value;
6. int len = count;
7.
8. for (int i = 0; i < len; i++) {
9. 31*h + val[off++];
10. }
11. hash = h;
12. }
13. return h;
14. }
这个测试的例子中,当注释重写的hashCode()方法时,这时默认返回对象的32JVM中的地址,两个不同的对象地址显然是不同的,我们在比较时,虽然通过重写的equals()方法比较出来userCd和userNm值是相同的,但是默认的hashCode()方法返回的值他们并不是同一个对象,所以我们通常要将hashCode()方法与equals()方法一起重写,以维护hashCode方法的常规协定,该协定声明相等对象必须具有相等的哈希码。
摘抄一句,用白话说,通过hashCode判断对象是否放在同一个桶里,然后再通过equals方法去判断这个桶里的对象是不是相同的,这个比喻是否挺形象,哈哈。
















