一.前言
在項目中經常會碰到按某些屬性是否相同去去除List集合中的重複對象的問題,每次看網上寫的都是什麼 “重寫自定義對象的equlas和hashCode”,千篇一律全是這樣,但是真實項目中自定義的對象可能在多個地方用到,每個地方的去重方式都可能不一樣,重寫肯定是不行的,今天就總結一下不重寫對象的equlas和hashCode,去除List中的重複對象。
二. 實現方式
假設我們有個對象User, 包含四個屬性: name、nickName、age、dept,需要根據name和age這兩個屬性去重,如果這兩個屬性相同就代表同一個對象
public class User {
// 姓名
private String name;
// 暱稱
private String nickName;
// 年齡
private Integer age;
// 部門
private String dept;
// 此處省略set和get方法
}
在list集合中添加5個User對象,分別如下:
public static void main(String[] args) {
List<User> userList = new ArrayList<>();
userList.add(new User("張三", "三兒", 20, "銷售部"));
userList.add(new User("李四", "四兒", 23, "銷售部"));
userList.add(new User("張三", "三兒", 20, "銷售部"));
userList.add(new User("張三", "三兒", 20, "研發部"));
userList.add(new User("王五", "五兒", 21, "研發部"));
}
現在我們想要去除userList集合中擁有相同姓名和年齡的User,但是又不想重寫User實體類的equlas和hashCode方法,那麼該怎麼做呢?
第一種方式:for循環倒敘刪除:
即:使用兩層循環,內層循環從後往前刪
// int size = userList.size(); 此處一定不要在這裏將size寫死,因爲size是一直在變的
for (int i = 0; i < userList.size(); i ++) {
User outU = userList.get(i);
for (int j = userList.size() - 1; j > i; j--) { // 內層循環從 size() -1開始
User inU = userList.get(j);
if (inU.getName().equals(outU.getName()) && inU.getAge() == outU.getAge()) {
userList.remove(j);
}
}
}
結果如下:
已經成功的刪除掉了相同姓名和年齡的對象。
第二種方式:使用Set集合去除重複元素:
Set<User> set = new TreeSet<>(new Comparator<User>() {
@Override
public int compare(User o1, User o2) {
// 這裏按照自己的需求來添加屬性即可
return (o1.getName().compareTo(o2.getName())) + (o1.getAge() - o2.getAge()));
};
});
set.addAll(userList);
printList(new ArrayList<>(set));
開始在這裏有點疑問,當時不明白爲什麼加入一個new Comparator比較器重寫compart方法就可以去重呢? 一個“比較”的方法還能夠去重? 後來看了一個Set的源碼搞明白了,其實Set集合的底層是用Map實現的,去重的原理即是用到了比較,首先看hashCode是否相同,如果相同再去比較equals,如果equals也相同就不再存儲,而我們的比較器Comparator,正是實現這個比較。