问题由来,在平常开发中我们经常用到导入功能,将模板中的数据封装成对象装到集合中,一个集合容器里面有很多重复的对象,里面的对象没有主键,但是根据业务的需求,重复的数据是不能导入并且及时给予提示!
创建实体对象
public class Student {
private String stuId;
private String stuName;
private String sex;
public Student(String stuId, String stuName, String sex) {
this.stuId = stuId;
this.stuName = stuName;
this.sex = sex;
}
public String getStuId() {
return stuId;
}
public void setStuId(String stuId) {
this.stuId = stuId;
}
public String getStuName() {
return stuName;
}
public void setStuName(String stuName) {
this.stuName = stuName;
}
public String getSex() {
return sex;
}
public void setSex(String sex) {
this.sex = sex;
}
@Override
public String toString() {
return "Student{" +
"stuId='" + stuId + '\'' +
", stuName='" + stuName + '\'' +
", sex='" + sex + '\'' +
'}';
}
}
模拟集合
List<Student> stuList = new ArrayList<Student>();
stuList.add(new Student("S001", "张三", "女"));
stuList.add(new Student("S002", "李四", "男"));
stuList.add(new Student("S001", "张三", "女"));
stuList.add(new Student("S002", "李四", "男"));
stuList.add(new Student("S003", "王五", "男"));
stuList.add(new Student("S004", "赵六", "女"));
方法一:遍历实体类的每一个属性
遍历实体类的每一个属性并判断是否重复。
测试方法:
/**
* 方法一:遍历实体类的每一个属性,
*/
List<Student> newStus = new ArrayList<Student>();
for (Student stu : stuList) {
if(ObjectUtils.isEmpty(stuList)){
newStus.add(stu);
}
boolean isSame = false;
for (Student s : newStus) {
if(s.getStuId().equals(stu.getStuId()) && s.getStuName().equals(stu.getStuName()) && s.getSex().equals(stu.getSex())){
isSame = true;
break;
}
}
if(isSame == false){
newStus.add(stu);
}
}
// 输出结果
System.out.println(newStus);
}
结果:
[Student{stuId='S001', stuName='张三', sex='女'}, Student{stuId='S002', stuName='李四', sex='男'}, Student{stuId='S003', stuName='王五', sex='男'}, Student{stuId='S004', stuName='赵六', sex='女'}]
方法二:利用list中contains方法去重
利用list中contains方法去重,在使用contains()之前,必须要重写equals()方法!
Student重写equals():
@Override
public boolean equals(Object obj) {
if (this == obj) return true;
if (obj == null || getClass() != obj.getClass()) return false;
Student student = (Student) obj;
//当stuId、stuName、sex内容都相等的时候,才返回true
return Objects.equals(stuId, student.stuId) &&
Objects.equals(stuName, student.stuName) &&
Objects.equals(sex, student.sex);
}
测试方法:
/**
* 方法二:利用list中contains方法去重
*/
List<Student> newList = new ArrayList<Student>();
//使用contain判断,是否有相同的元素
for (Student s : stuList) {
if(!newList.contains(s)){
newList.add(s);
}
}
//输出结果
System.out.println(newList);
结果:
[Student{stuId='S001', stuName='张三', sex='女'}, Student{stuId='S002', stuName='李四', sex='男'}, Student{stuId='S003', stuName='王五', sex='男'}, Student{stuId='S004', stuName='赵六', sex='女'}]
方法三:java 8中流式去重操作
利用 jdk1.8 中提供的Stream.distinct()列表去重,Stream.distinct()使用hashCode()和equals()方法来获取不同的元素,因此使用这种写法,对象需要重写hashCode()和equals()方法!
Student类重写hashCode()
@Override
public int hashCode() {
return Objects.hash(stuId, stuName, sex);
}
测试方法:
/**
* 方法三:java 8中流式去重操作
*/
List<Student> newList = stuList.stream().distinct().collect(Collectors.toList());
//输出结果
System.out.println(newList.toString());
结果:
[Student{stuId='S001', stuName='张三', sex='女'}, Student{stuId='S002', stuName='李四', sex='男'}, Student{stuId='S003', stuName='王五', sex='男'}, Student{stuId='S004', stuName='赵六', sex='女'}]
方法四:HashSet去重
利用set集合的天然不支持重复元素特性,用set集合判重必须重写Object中的equals()和hashCode(),重写Object中的equals()和hashCode()同方法二和方法三种一致!
测试方法:
/**
* 方法四:HashSet去重
*/
List<Student> newList = new ArrayList<Student>();
//set去重
HashSet<Student> set = new HashSet<>(stuList);
newList.addAll(set);
System.out.println(newList.toString());
结果:
[Student{stuId='S004', stuName='赵六', sex='女'}, Student{stuId='S002', stuName='李四', sex='男'}, Student{stuId='S003', stuName='王五', sex='男'}, Student{stuId='S001', stuName='张三', sex='女'}]
总结:四种方法去重效果一致,前三种方法输出的顺序保持一致(有序),第四种用HashSet去重打印的结果是无序的,因为set集合存放的数据本身就是无序且不可重复的!