> 文章列表 > Java 8中新特性Stream的详细理解和使用

Java 8中新特性Stream的详细理解和使用

Java 8中新特性Stream的详细理解和使用

Java 8中新特性Stream的基本理解和使用

Stream基本概念

Stream流是来自数据源的元素队列并支持聚合操作

**元素:**是特定类型的对象,是数据源形成的一个队列。Java中Stream不会存储元素,而是按需计算

数据源:Stream流数据的来源。可以是集合,数组,I/O Channel ,产生器Generator等

聚合操作:类似SQL语句的一系列操作,比如filter,map,sorted等。

Stream不是集合元素,不是数据结构来保存数据,是一个有关数据算法和计算的流:

获取一个数据源source => 数据转换 => 执行操作获取需要的结果,每次转换后原来的Stream对象不变,返回一个新的Stream对象,这样可以使得对Stream的操作链式排列,形成一个管道

还是不能理解?

简洁理解

Stream是对集合Collection对象功能的增强,Stream可以对集合对象进行便利高效的聚合操作和大批量的数据操作,集合类存有的元素都是划分内存空间存储的,数据量很大的集合类会占用大量的内存。Stream的元素是延迟计算的,即只有在访问的时候才会进入内存进行计算。

其次集合类的迭代逻辑是调用者负责的,通常使用for循环。Stream中的迭代是隐含在对Stream的各种操作当中的。

Stream操作的基本特征:

****Pipelining:****中间操作都会返回流本身。多个操作可以串成一个管道。这样就可以对操作进行优化,比如延迟执行和短路

内部迭代:对集合的遍历都是Iterator或者是for-Each操作,显示地在集合外部进行迭代。Stream提供了内部迭代的方式,通过访问者模式Vistor实现

Stream的特点:

不存储:

数据流Stream不是存储元素的数据结构

数据流Stream将数据元素从源数据 结构,数组,生成器函数和输入输出管道中传递到计算机操作的管道中

功能性:

一个数据流Stream中的流操作都会产生一个结果,不会修改源数据Stream中的元素

延迟计算

许多流操作中的各种操作,比如过滤,映射,去重等,只有访问时才会进行计算,这样可以有更多的机会进行优化

无界性

集合的大小是有界的,但数据流Stream可以是无界的,短路操作等可以允许无限流计算在有限的时间内完成。

如何生成流 ?

集合接口有两种方式生成流:

stream():为集合创建串行流

paralleStream():为集合创建并行流,并行流可以充分发挥多核处理器的优势,使用fork和join并行方式来拆分任务和加速处理过程

stream()

创建第一个示例:

实际运用:如项目中查找学生成绩为空的学生信息

****注意:****Arrays.asList()是一个Java数组与集合之间的桥梁方法,它可以将一个数组转换为一个List集合。使用Arrays.asList()方法,我们可以将一个数组转换为一个List集合,然后使用List的方法来操作这个集合

//输出不是空的字符串List<String> strings= Arrays.asList("abs","","dda","","dark","");List<String> filtered = strings.stream().filter(string -> !string.isEmpty()).collect(Collectors.toList());System.out.println(filtered);

运行结果:

在这里插入图片描述

forEach和limit

提供更好的遍历方式,遍历数据

Stream 提供新的方法 ’ forEach‘ 来迭代流中的每个数据。

limit方法用于获取指定数量的流

通过流方式随机打印10条数据

//使用forEach输出10个随机数Random random = new Random();random.ints().limit(15).forEach(System.out::println);

运行结果:

在这里插入图片描述

map

map方法用于映射每个元素到对应的结果

        //使用map输出元素的2的倍数List<Integer> numbers = Arrays.asList(155,151,4,56,2,3,15,30);List<Integer> dList = numbers.stream().map(x -> 2*x).collect(Collectors.toList());System.out.println(dList);

运行结果:

在这里插入图片描述

filter

filter 方法用于通过设置的条件过滤出元素

//使用filter方法过滤出空字符串List<String> strings1 = Arrays.asList();//获取空字符串的数量long count = strings1.stream().filter(string -> string.isEmpty()).count();System.out.println(count);

在这里插入图片描述

sorted

sorted方法用于对流进行排序

对随机生成的数进行排序:

        //使用forEach输出10个随机数//ints()返回的是整数值最大到最小(即Long范围内)Random random = new Random();random.ints().limit(10).sorted().forEach(System.out::println);

运行结果:

在这里插入图片描述

Collectors(收集器)

Collectors类实现了很多规约操作(即将数据流收集成另外一种数据格式,如:toList、toSet、toMap等数据结构),将流数据转换为集合或者聚合集合。之前字符串拼接一般是用StringBuffer的append()方法。在JDK8中,可以采用函数式编程(使用Collectors.join 收集器)的方式对字符串进行更优雅的拼接。Collectors.joining收集器:支持灵活的参数配置,可以指定字符串连接时的分隔符,前缀和后缀字符串

示例1:

        //定义一个String类型的集合List<String> strings2 = Arrays.asList("abs","","dda","","dark","");//将strings2字符串集合按照非空的条件过滤筛选出来到一个新集合内List<String> filtered1 = strings2.stream().filter(string -> !string.isEmpty()).collect(Collectors.toList());System.out.println("筛选后的字符串集合:"+filtered1);//将filtered1集合通过Collectors聚合为一个字符串,按“”的方式连接String mergedString = strings2.stream().filter(string -> !string.isEmpty()).collect(Collectors.joining());System.out.println("合拼的字符串"+mergedString);

运行结果:没有任何分隔符的将字符串合拼在一起

在这里插入图片描述

示例2:

String mergedString = strings2.stream().filter(string -> !string.isEmpty()).collect(Collectors.joining("->"));

运行结果:通过"->"分隔符将字符串拼接

在这里插入图片描述

示例3:

String mergedString1 = strings2.stream().filter(string -> !string.isEmpty()).collect(Collectors.joining("-》","{","}"));System.out.println("合拼的字符串2:"+mergedString1);

运行结果:通过"-》"分隔拼接的同时同时设置前缀和后缀

在这里插入图片描述

统计

另外,一些产生统计结果的收集器也很有用

如:开发时会对价格进行求平均,总和,找到最大或者最小值时就能便捷的使用

示例:

        SqlSession sqlSession = sqlSessionUtil.getSqlSession();//获取StudentDao对象StudentDao studentDao = sqlSession.getMapper(StudentDao.class);//获取所有学生对象信息List<Student> list = studentDao.getAllStudents();list.forEach(System.out::println);IntSummaryStatistics summaryStatistics = list.stream().mapToInt(student -> student.getSage()).summaryStatistics();System.out.println("他们的年龄和为:" + summaryStatistics.getSum());System.out.println("他们的平均年龄为:"+summaryStatistics.getAverage());System.out.println("他们之间最大年龄为:"+summaryStatistics.getMax());System.out.println("他们之间最小年龄为:"+summaryStatistics.getMin());System.out.println("数据库中总的数据条数为:"+summaryStatistics.getCount());

运行结果:

在这里插入图片描述

parallelStream

parallelStream是流并行处理程序的代替方法,可以和stream()的顺序运行之间任意切换

//使用filter方法过滤出空字符串List<String> strings1 = Arrays.asList("abs","","dda","","dark","");//获取空字符串的数量long count = strings1.parallelStream().filter(string -> string.isEmpty()).count();System.out.println(count);

运行结果:

在这里插入图片描述