Bootstrap

Stream流处理list分组方法

工作中经常碰到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等,这里就不多说了。

原创文章分享请注明出处

;