前言
后续学习到网络编程、并发编程,发现JavaSE中还有个Stream流没有系统的复习
流在jdk1.8之前是IO流,jdk1.8新添加了stream特性用于处理集合
这两者是不同的
目录
IO流
jdk1.8之前就存在流,它属于IO包(java.io),用于数据传输
IO流的使用很简单,就是调用API,重点在明白它有哪些类
分类
有很多类型的IO流
- 根据处理单位可以分为字符流与字节流
1字符 = 2字节 、 1字节(byte) = 8位(bit)
一个汉字占两个字节,使用字符流就可以正确的传输中文
系统的输入输出(System.in,System.out)都是字节流
-
根据数据传输方向分为输入流、输出流
-
根据功能不同分为节点流、处理流
节点流(低级流)是指程序可以向一个特定的节点读写数据,直接连接数据源,常见的File流
处理流(高级流)是建立在节点流的基础上,处理流并不直接连接数据源,它大多情况是对已存在的节点流进行包装,是一种典型的装饰器设计模式。使用处理流主要是为了更方便的执行输入输出工作
新特性:Stream
首先新特性stream不像传统IO流,它是用于对集合Connection的操作
jdk1.8中,引入了Lambda和Stream
引进的Lambda的函数式编程
新特性Stream能够让用户以函数式的方式、更为简单的操纵集合等数据结构,并实现了用户无感知的并行计算
集合使用
常用方法:最简单的遍历
package com.company.javaBasis.Stream;
import java.util.LinkedList;
import java.util.List;
public class NewStream {
public static void main(String[] args){
List<Integer> list=new LinkedList<>();
list.add(1);
list.add(2);
list.add(3);
//foreach循环遍历
for(int i:list){
System.out.println(i);
}
}
}
使用stream流遍历
package com.company.javaBasis.Stream;
import java.util.LinkedList;
import java.util.List;
public class NewStream {
public static void main(String[] args){
List<Integer> list=new LinkedList<>();
list.add(1);
list.add(2);
list.add(3);
//stream流遍历
//Lambda方法引用
list.stream().forEach(System.out::println);
}
}
stream流代码更加简单优雅,stream并没有把遍历的实现算法写出,而是一种封装的形式,让我们更专注于“做什么”,而不是怎么做
stream将集合常用的操作封装,需要用时只需要调用API即可
Stream操作
Stream操作可以分为3步:创建流、中间操作、结束操作
创建流
java.util.stream.Stream< T> 是Java 8新加入的常用的流接口。(这并不是一个函数式接口。)
创建一个流有两种方法:
1. 集合的stream方法创建
Stream streamlist=list.stream();
streamlist.forEach(System.out::println);
2. Stream接口提供创建方法
- of
其生成的Stream是有限长度的,Stream的长度为其内的元素个数
of方法的参数是个泛型参数< T >,可以返回一个数组
Stream stream=Stream.of(list);
stream.forEach( i->System.out.println(i));
- generator
返回一个无限长度的Stream,其元素由Supplier接口的提供
只封装了一个get()方法,其用来返回任何泛型的值
常用与产生随机数
Stream stream=Stream.generate(new Supplier<Object>() {
@Override
public Object get() {
return Math.random();
}
});
stream.forEach(System.out::println);
- iterate
返回的也是一个无限长度的Stream,与generate方法不同的是,其是通过函数f迭代对给指定的元素种子而产生无限连续有序Stream,其中包含的元素可以认为是:seed,f(seed),f(f(seed))无限循环
Stream stream=Stream.iterate(1, item -> item + 1);
stream.limit(10).forEach(System.out::println);
- empty
empty方法返回一个空的顺序Stream,该Stream里面不包含元素项
Stream streams=Stream.empty();
中间操作
中间操作就是对Stream流操作,返回的还是一个Stream
中间操作常用的方法有:
- 遍历foreach
list.stream().forEach(System.out::println);
- 过滤filter
filter方法对原Stream按照指定条件过滤,在新建的Stream中,只包含满足条件的元素,将不满足条件的元素过滤掉
Stream.of(1,2,3,4,5).filter(i -> i>3).forEach(System.out::println);
- Map映射
将对于Stream中包含的元素使用给定的转换函数进行转换操作,新生成的Stream只包含转换生成的元素
封装好了3中变形:mapToDouble,mapToInt,mapToLong
Stream.of(1,2,3,4,5).map(i->i.doubleValue()).forEach(System.out::println);
- peek
peek方法生成一个包含原Stream的所有元素的新Stream,同时会提供一个消费函数(Consumer实例),新Stream每个元素被消费的时候都会执行给定的消费函数,并且消费函数优先执行
(但是如果没有执行最终操作,这个消费函数也不会运行)
Stream.of(1,2,3,4,5).peek(System.out::println);
Stream.of(1,2,3,4,5).peek(System.out::println).forEach(System.out::println);
不仅有最终操作遍历输出,还有消费函数输出
中间操作还有很多API,具体运用时再查找
结束操作
中间操作返回的还是stream流对象,结束操作返回的不再是Stream对象,调用了最终操作的方法,Stream才会执行
对于结束操作和中间操作的API区别:中间操作返回的是Stream流对象,结束操作返回的不是
还有很多,当然最常用的还是foreach
总结
- 传统IO流是用于传输数据
- JDK1.8的新特性Stream流与传统的IO流是不同的,Stream流用于增强集合的操作
- Stream有两个特性:惰性求值(中间操作返回的是Stream流对象)、函数式编程接口(类Lambda)
- Stream操作分为3步:创建Stream、中间操作、结束操作,都完成后才会完成Stream操作
- 在数据量小的情况下还是迭代器效率更高,在多核数据量大的情况下stream流操作效率更高