5、转换Stream流

1、概念

转换Stream其实就是把一个Stream通过某些行为转换成一个新的Stream

多个转换可以连接起来形成一个流水线,除非流水线上触发终止操作,否则转换操作不会执行任何的处理,而是在终止操作时候一次性全部处理,称为“惰性求值”。

2、筛选与切片

2.1、filter

filter 对于Stream中包含的元素使用给定的过滤函数进行过滤操作,新生成的Stream只包含符合条件的元素

image

下面的代码就是过滤出年纪大于25岁的学生

        List<Student> studentList = new ArrayList<>();
        studentList.add(new Student(1, "赵迪", 23));
        studentList.add(new Student(2, "tom", 25));
        studentList.add(new Student(2, "jack", 27));
        studentList.add(new Student(2, "rose", 22));

        List<Student> newList = studentList.stream().filter(x->x.getAge()>25).collect(Collectors.toList());
        System.out.println(newList);//[Student(id=2, name=jack, age=27)]

2.2、limit

limit 对一个Stream进行截断操作,获取其前N个元素,如果原Stream中包含的元素个数小于N,那就获取其所有的元素

image

下面的代码就是过滤出前2个学生

        List<Student> studentList = new ArrayList<>();
        studentList.add(new Student(1, "赵迪", 23));
        studentList.add(new Student(2, "tom", 25));
        studentList.add(new Student(2, "jack", 27));
        studentList.add(new Student(2, "rose", 22));

        List<Student> newList = studentList.stream().limit(2).collect(Collectors.toList());
        System.out.println(newList);//[Student(id=1, name=赵迪, age=23), Student(id=2, name=tom, age=25)]

2.3、skip

skip 跳过指定的个数,返回一个丢弃原Stream的前N个元素后剩下元素组成的新Stream,如果原Stream中包含的元素个数小于N,那么返回空Stream

image

下面的代码就是跳过前面2个学生

        List<Student> studentList = new ArrayList<>();
        studentList.add(new Student(1, "赵迪", 23));
        studentList.add(new Student(2, "tom", 25));
        studentList.add(new Student(2, "jack", 27));
        studentList.add(new Student(2, "rose", 22));

        List<Student> newList = studentList.stream().skip(2).collect(Collectors.toList());
        System.out.println(newList);//[Student(id=2, name=jack, age=27), Student(id=2, name=rose, age=22)]

2.4、distinct

distinct 表示对stream中的元素进行去重操作,得到新的stream不存在重复的元素,去重的逻辑依赖元素的equals方法
image

下面的代码是去重学生,根据ID

        List<Student> studentList = new ArrayList<>();
        studentList.add(new Student(1, "赵迪", 23));
        studentList.add(new Student(2, "tom", 25));
        studentList.add(new Student(2, "tom", 27));
        studentList.add(new Student(2, "rose", 22));

        List<Student> newList = studentList.stream().distinct().collect(Collectors.toList());

3、映射

SQL中,借助SELECT关键字后面添加需要的字段名称,可以仅输出我们需要的字段数据,而流式处理的映射操作也是实现这一目的,在java8的流式处理中,主要包含两类映射操作:mapflatMap

3.1、map

将元素转换成其他形式或提取信息。接收一个函数作为参数,该函数会被应用到每个元素上,并将其映射成一个新的元素。

image

下面的代码就是通过map将student的年纪映射出来

        List<Student> studentList = new ArrayList<>();
        studentList.add(new Student(1, "赵迪", 23));
        studentList.add(new Student(2, "tom", 25));
        studentList.add(new Student(2, "tom", 27));
        studentList.add(new Student(2, "rose", 22));

        studentList.stream().map(x -> x.getAge()).collect(Collectors.toList());
        List<Integer> newList = studentList.stream().map(x -> x.getAge()).collect(Collectors.toList());
        System.out.println(newList);//[23, 25, 27, 22]

3.2、flatMap

与map类似,不同的是其每个元素转换得到的是Stream对象,会把子Stream中的元素压缩到父集合中,也就是说,将流中的每一个值都换成另一个流,然后把所有流连成一个流。

image

3.3、map和flatMap区别

举例子说明

有二箱鸡蛋,每箱5个,现在要把鸡蛋加工成煎蛋,然后分给学生。

map做的事情:把二箱鸡蛋分别加工成煎蛋,还是放成原来的两箱,分给2组学生;

flatMap做的事情:把二箱鸡蛋分别加工成煎蛋,然后放到一起【10个煎蛋】,分给10个学生;

4、排序

排序主要分为两种,第一种就是自然排序,第二种就是定制排序

4.1、自然排序(java.lang.Comparable)

Comparable接口强行对实现它的每个类的对象进行整体排序,这种排序被称为类的自然排序

实现 Comparable 的类必须实现 compareTo(Object obj) 方法,两个对象即 通过 compareTo(Object obj) 方法的返回值来比较大小。如果当前对象this大 于形参对象obj,则返回正整数,如果当前对象this小于形参对象obj,则返回 负整数,如果当前对象this等于形参对象obj,则返回零。

实现Comparable接口的对象列表(和数组)可以通过 Collections.sortArrays.sort进行自动排序。实现此接口的对象可以用作有序映射中的键或有 序集合中的元素,无需指定比较器。


@Data
@AllArgsConstructor
@NoArgsConstructor
public class Student implements Comparable {

    private Integer id;

    private String name;

    private Integer age;

    @Override
    public int compareTo(Object o) {
        Student other = (Student) o;
        if (this.getAge() > other.getAge()) {

            return 1;
        } else if (this.getAge() < other.getAge()) {
            return -1;
        }
        return 0;
    }
}

上述代码中,Student类实现了Comparable接口,并且实现了comparaTo方法

public class StreamDemo01 {
    public static void main(String[] args) {
        List<Student> studentList = new ArrayList<>();
        studentList.add(new Student(1, "赵迪", 23));
        studentList.add(new Student(3, "tom", 25));
        studentList.add(new Student(2, "tom", 27));
        studentList.add(new Student(2, "rose", 22));
        List<Student> list = studentList.stream().sorted().collect(Collectors.toList());
        System.out.println(list);
    }
}

上述代码按照age进行由低到高排序,结果如下

[Student(id=2, name=rose, age=22), Student(id=1, name=赵迪, age=23), Student(id=3, name=tom, age=25), Student(id=2, name=tom, age=27)]

4.2、定制排序(java.util.Comparator)

当元素的类型没有实现java.lang.Comparable接口而又不方便修改代码,或者实现了java.lang.Comparable接口的排序规则不适合当前的操作,那么可以考虑使用Comparator的对象来排序,强行对多个对象进行整体排序的比较。

重写compare(Object o1,Object o2)方法,比较o1和o2的大小:如果方法返 回正整数,则表示o1大于o2;如果返回0,表示相等;返回负整数,表示 o1小于o2

可以将Comparator传递给sort方法(如 Collections.sort Arrays.sort), 从而允许在排序顺序上实现精确控制

public class StreamDemo01 {
    public static void main(String[] args) {
        List<Student> studentList = new ArrayList<>();
        studentList.add(new Student(1, "赵迪", 23));
        studentList.add(new Student(3, "tom", 25));
        studentList.add(new Student(2, "tom", 27));
        studentList.add(new Student(2, "rose", 22));
        Comparator<Student> comparator = new Comparator<Student>() {
            @Override
            public int compare(Student o1, Student o2) {
                return o1.getId() - o2.getId();
            }
        };
        List<Student> list = studentList.stream().sorted(comparator).collect(Collectors.toList());
        System.out.println(list);
    }

上述代码中,自定义比较器comparator,传递给sorted,按照id从小到大排序,结果如下

[Student(id=1, name=赵迪, age=23), Student(id=2, name=tom, age=27), Student(id=2, name=rose, age=22), Student(id=3, name=tom, age=25)]

posted @ 2020-08-05 00:01  墮落方能自由  阅读(422)  评论(0编辑  收藏  举报