设为首页 加入收藏

TOP

Java 8 Stream API 引入和使用(一)
2023-07-25 21:27:31 】 浏览:72
Tags:Java Stream API

Java 8 系列文章 持续更新中

引入流

流是什么

流是Java API的新成员,它允许你以声明性的方式处理数据集合。可以看成遍历数据集的高级迭代。流可以透明地并行处理,无需编写多线程代码。我们先简单看一下使用流的好处。下面两段代码都是用来返回年龄小于14岁的初中生的姓名,并按照年龄排序。

假如我们有下面Student实体类

@Data
public class Student {
    private String name;
    private int age;
    private boolean member;
    private Grade grade;
    public Student() {
    }
    public Student(String name, int age, boolean member, Grade grade) {
        this.name = name;
        this.age = age;
        this.member = member;
        this.grade = grade;
    }
    public enum Grade{
        JUNIOR_ONE,JUNIOR_TWO,JUNIOR_THREE
    }
}

Java 8之前的实现方式:

List<Student> students = Arrays.asList(
        new Student("张初一", 13, false, Student.Grade.JUNIOR_ONE),
        new Student("李初二", 14, false, Student.Grade.JUNIOR_TWO),
        new Student("孙初三", 15, false, Student.Grade.JUNIOR_THREE),
        new Student("王初一", 12, false, Student.Grade.JUNIOR_ONE),
        new Student("钱初二", 14, false, Student.Grade.JUNIOR_TWO),
        new Student("周初三", 16, false, Student.Grade.JUNIOR_THREE));
List<Student> resultStudent = new ArrayList<>(); //垃圾变量,一次性的中间变量
//foreach循环,根据条件筛选元素
for (Student student : students) {
    if (student.getAge() < 14) {
        resultStudent.add(student);
    }
}
//匿名类,给元素排序
Collections.sort(resultStudent, new Comparator<Student>() {
    @Override
    public int compare(Student o1, Student o2) {
        return Integer.compare(o1.getAge(), o2.getAge());
    }
});
List<String> resultName = new ArrayList<>();
//foreach循环,获取元素属性
for (Student student : resultStudent) {
    resultName.add(student.getName());
}

Java 8流的实现方式:

List<String> resultName = students.stream()
        .filter(student -> student.getAge() < 14) //年龄筛选
        .sorted(Comparator.comparing(Student::getAge)) //年龄排序
        .map(Student::getName) //提取姓名
        .collect(Collectors.toList());//将提取的姓名保存在List中

为了利用多核架构并行执行这段代码,只需要把stream()替换成parallelStream()即可。

通过对比两段代码之后,Java8流的方式有几个显而易见的好处。

  • 代码是以声明性的方式写的:说明想要做什么(筛选小于14岁的学生)而不是去说明怎么去做(循环、if)
  • 将几个基础操作链接起来,表达复杂的数据处理流水线(filter->sorted->map->collect),同时保持代码清晰可读。

总结一下,Java 8的Stream API带来的好处:

  • 声明性-更简洁,更易读
  • 可复合-更灵活
  • 可并行-性能更好

流简介

流到底是什么?简单定义:“从支持数据处理操作的源生成的元素序列”,下面剖析这个定义。

  • 元素序列:像集合一样,流也提供了一个接口,可以访问特定元素类型的一组有序值。集合讲的是数据,流讲的是计算。
  • :流使用一个提供数据的源,如集合、数组或输入/输出资源。
  • 数据处理操作:流的数据处理功能之处类似于数据库的操作,以及函数式编程语言中的常用操作,如filter、map、reduce、find、match、sort等。流的操作可以顺序执行,也可以并行执行。
  • 流水线:很多流的操作会返回一个流,这样多个操作就可以链接起来,形成一个流水线。可以看成数据库式查询。
  • 内部迭代:于迭代器显示迭代的不同,流的迭代操作是在背后进行的。

看一段代码,更好理解这些概念

List<String> resultName = students.stream() //从列表中获取流
        .filter(student -> student.getAge() < 16) //操作流水线:筛选
        .map(Student::getName) //操作流水线:提取姓名
        .limit(2) //操作流水线:只取2个
        .collect(Collectors.toList());//将结果保存在List中

在上面代码中,数据源是学生列表(students),用来给流提供一个元素序列,调用stream()获取一个流,接下来就是一系列数据处理操作:filter、map、limit和collect。除collect之外,所有这些操作都会返回一个流,组成了一条流水线。最后collect操作开始处理流水线,并返回结果。

流与集合

粗略的说,流与集合之间的差异就在于什么时候进行计算。

  • 集合是一个内存中的数据结构(可以添加或者删除),它包含数据结构中目前所有的值——集合中的每个元素都是预先处理好然后添加到集合中的。
  • 流则是在概念上固定的数据结构(不能添加或删除元素),其元素是按需计算的。

在哲学中,流被看作在时间中分布的一组值,而集合则是空间(计算机内存)中分布的一组值,在一个时间点上全体存在。

只能遍历一次

和迭代器类似,流只能遍历一次。遍历完成之后,我们说这个流已经被消费掉了。

例如下面的代码会抛出异常

Stream<Student> stream = students.stream();
stream.forEach(System.out::println);
stream.forEach(System.out::println);

执行之后抛出

首页 上一页 1 2 3 4 5 下一页 尾页 1/5/5
】【打印繁体】【投稿】【收藏】 【推荐】【举报】【评论】 【关闭】 【返回顶部
上一篇JUC中的AQS底层详细超详解 下一篇SpringCloud(一) - Dubbo + Zooke..

最新文章

热门文章

Hot 文章

Python

C 语言

C++基础

大数据基础

linux编程基础

C/C++面试题目