存储的数据类型是基本数据类型,可直接将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方法去判断这个桶里的对象是不是相同的,这个比喻是否挺形象,哈哈。