工作中经常碰到list去重的问题,现在我简单分享一下我的处理方式。
@Data
@Accessors(chain = true)
@NoArgsConstructor
@AllArgsConstructor
class Student {
/**
* 姓名
*/
private String name;
/**
* 年龄
*/
private Integer age;
/**
* 性别,0和1
*/
private Integer sex;
/**
* 描述
*/
private String desc;
/**
* 班级id,1.2.3...
*/
private Integer classId;
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (!(o instanceof Student)) return false;
Student student = (Student) o;
return getName().equals(student.getName());
}
@Override
public int hashCode() {
return Objects.hash(getName());
}
}
class TestList{
public static void main(String[] args) {
List<Student> studentList = new ArrayList<>();
studentList.add(new Student("张飞",48,0,"皮肤有点黑",2));
studentList.add(new Student("关羽",50,0,"关羽字云长",2));
studentList.add(new Student("吕布",51,0,"吕布字奉先",4));
studentList.add(new Student("张飞",48,0,"张飞字翼德",2));
studentList.add(new Student("张飞",22,0,"张飞字翼德",3));
studentList.add(new Student("赵云",48,0,"赵云字子龙",2));
studentList.add(new Student("马超",25,0,"马超子孟起",2));
studentList.add(new Student("黄忠",48,0,"黄忠字汉升",2));
studentList.add(new Student("夏侯渊",26,0,"夏侯渊字妙才",1));
studentList.add(new Student("夏侯惇",68,0,"夏侯惇字元让",1));
studentList.add(new Student("曹仁",48,0,"曹仁不知道",1));
studentList.add(new Student("甘宁",61,0,"甘宁字兴霸",3));
studentList.add(new Student("周泰",48,0,"周泰不知道",3));
studentList.add(new Student("诸葛亮",15,0,"孔明",2));
studentList.add(new Student("周瑜",64,0,"不知道",3));
studentList.add(new Student("司马懿",578,0,"仲达",1));
studentList.add(new Student("司马懿",46,0,"仲达",1));
studentList.add(new Student("张飞",58,0,"假张飞",2));
studentList.add(new Student("赵云",57,0,"高达赵云",5));
studentList.add(new Student("吕布",57,0,"皮肤有点黑",4));
studentList.add(new Student("貂蝉",18,0,"沉鱼落雁",4));
studentList.add(new Student("甄姬",18,0,"闭月羞花",2));
//手工创建一些数据测试
//情形一,名字相同的全部当做重复
Set<Student> nameSet = new HashSet<>();
for (Student s:studentList) {
nameSet.add(s);
}
for (Student s:nameSet) {
System.out.println(s);
}
}
}
这种利用set去重,代码也不算多,但是并不能实现复杂的情形,下面介绍java8的stream流处理
Map<String,List<Student>> map = studentList.stream().collect(Collectors.groupingBy(Student::getName));
MapUtils.verbosePrint(System.out,"打印",map);
结果
上面利用到collect收集器里面的分组方法,用过name分组得到map,这样子去重复就很简单。
在重写过hashCode和equals方法直接用下面的更简单,直接利用distinct,就像mysql里面的差不多
studentList.stream().distinct().collect(Collectors.toList()).stream().forEach(System.out::println);
现在说一下稍微复杂的业务,根据名字和class分组,也就是说名字和班级都相同的才算重复
这种情况重新封一个对象利用set也是挺方便的
我这里介绍一下双重分组
Map<String,Map<Integer,List<Student>>> map1 = studentList.stream().collect(Collectors.groupingBy(Student::getName,Collectors.groupingBy(Student::getClassId)));
MapUtils.verbosePrint(System.out,"打印",map1);
结果
具体的分组我并没有做,这种分组得到map再来处理也挺麻烦的,各种工具包也有挺多的分组去重的方法。
这里只是说了一下java8stream的方便,代码确实优雅很多。
此外stream流提供了多种其他的方法,比如map,filter等,这里就不多说了。
原创文章分享请注明出处