什么是Stream
Stream是Java8的新增的一个接口,主要用于简化集合或数组的筛选, 排序,聚合等操作,简单点说就是迭代的替代方案
如何获得Stream对象
数组流化:
无论是对象数组还是基本类型的数组都是调用数据工具类的stream方法或者Stream流类方法中的of方法获取流化对象。
语法:Arrays.stream(ArrayObject) OR Stream.of(ArrayObject)
集合流化:对于集合的流化可分为Collect和Map的流化。
Collect的流化较为简单,直接调用该对象成员方法中的stream或parallelStream方法即可。
语法:CollectObject.stream() OR CollectObject.parallelStream()
二者区别仅在于stream返回的是一个顺序流,而parallelStream方法返回的是一个并行流
Map的流化与Collect有些许区别,转流前需先调用该对象成员方法中的entrySet方法获取一个Set类型的映射对象集合,
在调用后者对象成员方法中的stream或parallelStream方法将其流化。
语法:MapObject.entrySet().stream()
Stream方法的操作类型
Stream对象方法的两种操作类型——中间操作 & 终止操作。
话不多说先上图。图片引用于
中间操作:方法返回值为Stream或其子实现类对象
中间操作的类型的方法完成后,会返回一条新的流,同时将原有流关闭,新的流包含着原有流中满足此次中间操作条件的所有元素。
终止操作:方法返回值为不为Stream或其子实现类对象
终止操作类型的方法完成后,会直接将原有流关闭。
一个流可以进行零次或多次中间操作。但只能进行一次终止操作。如果把对流中数据的操作看作加工,那么中间操作就是加工时的一道道工序,当然这类方法都是惰性化的,调用到中间方法时,并不真正进行流的遍历,而是记录遍历时需要进行的操作,而终止操作就是出厂前的包装。一但进行终止操作则代表着此次加工正式完成。且终止操作的执行,才会真正开始流的遍历。而所有的中间操作都会在这一次遍历中执行,所以无论流执行多少次中间操作,由于并未进行流的遍历,所以该操作的时间复杂度永远是0,只有当执行终止操作时,其时间复杂度才是1。
Stream的简单使用
使用前准备
Idea代码
public class Main {
private static ArrayList<Integer> numList;
public static void main(String[] args) {
init(5);
}
/**
* 集合初始化
*/
public static void init(int i) {
int size = i;
numList = new ArrayList(size);
Random random = new Random();
for (int j = 0; j < size; j++) {
numList.add(random.nextInt(128));
}
}
}
案例1:打印流中所有元素
public static void main(String[] args) {
init(5);
Stream<Integer> stream = numList.stream();
//stream.forEach(x->System.out.println(x));
stream.forEach(System.out::println);
}
控制台输出
案例2:打印流中第一个元素
public static void main(String[] args) {
init(5);
Stream<Integer> stream = numList.stream();
Optional<Integer> first = stream.findFirst();
if(first.isPresent()){
System.out.println(first.get());
}
}
控制台输出
案例3:打印流中任意元素
public static void main(String[] args) {
init(5);
Stream<Integer> stream = numList.stream();
Optional<Integer> any = stream.findAny();
if(any.isPresent()){
System.out.println(any.get());
}
}
控制台输出
案例4:打印流中除了前三个元素外的所有元素
public static void main(String[] args) {
init(5);
Stream<Integer> stream = numList.stream();
stream.skip(3).forEach(System.out::println);
}
控制台输出
案例5:打印流中不小于64的元素
Idea代码
public static void main(String[] args) {
init(5);
Stream<Integer> stream = numList.stream();
stream.filter(x -> x >= 64).forEach(System.out::println);
}
控制台输出
案例5:打印流中不小于64且升序排序后的元素
idea代码
public static void main(String[] args) {
init(5);
Stream<Integer> stream = numList.stream();
stream.filter(x -> x >= 64).sorted().forEach(System.out::println);
}
控制台输出
案例6:将流中不小于64的元素转为集合,并打印该集合
Idea代码
public static void main(String[] args) {
init(5);
Stream<Integer> stream = numList.stream();
List<Integer> collect = stream.filter(x -> x >= 64).sorted().collect(Collectors.toList());
System.out.println(collect);
}
控制台输出
案例7:将流中大于64的且升序排序后的元素转为String类型并保存到集合并打印
Idea代码
public static void main(String[] args) {
init(5);
Stream<Integer> stream = numList.stream();
List<String> collect = stream.filter(x -> x >= 64).sorted().map(x -> new StringBuilder("").append(x).toString()).collect(Collectors.toList());
System.out.println(collect);
}
控制台输出
总结
流不像集合或数组,后者有数据结构,而流没有,所以自身并没有集合或者数组那样的内部存储,流的操作都是操作管道从集合或数组中抓取数据,之后操作抓取到的数据,而不是像集合或数组的数据保存到自身,因此流的任何操作都不会影响到集合或数组中的数据。