-
Stream是对集合Collection对象功能的增强: Stream可以对集合对象进行便利高效的聚合操作和大批量的数据操作 集合类持有的元素都是存储在内存中,数据量很大的集合类会占用大量的内存 .Stream的元素是延迟计算的,只有在访问时才会进入内存进行计算 集合类的迭代逻辑是调用者负责的,通常使用for循环 .Stream中的迭代是隐含在对Stream的各种操作当中
-
Stream操作的两个基础特征: Pipelining: 中间操作都会返回流本身.多个操作可以串成一个管道.这样就可以对操作进行优化,比如延迟执行laziness和短路short-circuiting 内部迭代: 通常对集合的遍历都是通过Iterator或者forEach操作,显式地在集合外部进行迭代 .Stream提供了内部迭代的方式,通过访问者模式Visitor实现
-
Stream的特点: 不存储: 数据流Stream不是存储元素的数据结构 数据流Stream将数据元素从源数据结构,数组,生成器函数和输入输出管道中传递到计算操作的管道中 功能性: 一个数据流Stream中的流操作都会产生一个结果,不会修改源数据流Stream中的元素 延迟计算: 许多流操作中的各种操作,比如过滤,映射,去重等,只有访问时才会进行计算,这样可以有更多的机会进行优化 无界性: 集合的大小是有界的,但是数据流Stream可以是无界的 短路操作等可以允许无限流计算在有限的时间内完成
-
示例: 将流程转化为Java代码
±-------------------+ ±-----+ ±-----+ ±–+ ±------+
| stream of elements ±----> |filter±> |sorted±> |map±> |collect|
±-------------------+ ±-----+ ±-----+ ±–+ ±------+
List transactionsIds = widgets.stream()
.filter(b -> b.getColor == RED)
.sorted((x, y) -> x.getWeight() - y.getWeight())
.mapToInt(Widget :: getWeight)
.sum();
生成流
===
-
集合接口有两种方法来生成流:
-
stream(): 为集合创建串行流
-
parallelStream(): 为集合创建并行流 并行流可以充分发挥多核处理器的优势 使用fork和join并行方式来拆分任务和加速处理过程
List strings = Arrays.asList(“I”, “want”, “to”, “be”, “”, “great”);
List filter = strings.stream().filter(string -> !string.isEmpty()).collect(Collectors.toList());
Stream的创建方式
===========
数组
==
- 通过数组来生成Stream流
String[] arrayStr = {“a”, “b”, “c”};
// 使用Stream中的静态方法
Stream stream = Stream.of(arrayStr);
集合
==
- 通过集合来生成Stream流
List list = Arrays.asList(“a”, “b”, “c”);
Stream strem = list.stream();
Stream.generate()
=================
- 通过Stream.generate()方法来生成Stream流
Stream generate = Stream.generate(() -> 1);
Stream.iterate()
================
- 通过Stream.iterate()方法来生成Stream流
Stream iterate = Stream.iterate(1, x -> x + 1);
API
===
- 通过其余相关的API进行创建
String str = “api”;
IntStream stream = str.chars();
Stream常用方法
==========
中间操作
====
- 中间操作: 如果调用方法之后返回的结果是Stream对象的操作是一个中间操作
filter
======
- filter方法用于通过设置的条件过滤出元素
/*
- 过滤出空字符串的个数
*/
List strings = Arrays.asList(“I”, “want”, “to”, “be”, “”, “great”);
long count = Strings.stream().filter(string -> string.isEmpty()).count();
/*
- 过滤出偶数
*/
Arrays.asList(1, 2, 3, 4, 5).stream()
.filter(x -> x % 2 == 0)
// 2, 4
.forEach(System.out :: println)
/*
- 求出所有的偶数和
*/
int count = Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9).stream()
.filter(x -> x % 2 == 0)
.mapToInt(x -> x)
.sum();
System.out.println(count);
distinct
========
- distinct方法通过元素的hashcode()和equals()去除重复元素
Arrays.asList(1, 2, 3, 3, 3, 4, 5).stream()
.distinct()
// 1, 2, 3, 4, 5
.forEach(System.out :: println);
集合Set去重:
Arrays.asList(1, 2, 3, 4, 5).stream() .collect(Collectors.toSet()) // 1, 2, 3, 4, 5 .forEach(System.out :: println); 复制代码
sorted
======
-
sorted方法根据自然排序返回Stream流
-
sorted(Comparator comparator)方法根据提供的Comparator进行排序
/*
- 使用sorted方法实现min求最小值和max求最大值
*/
List list = Arrays.asList(1, 2, 3, 4, 5);
// 数字的自然排序就是从小到大
Optional min = list.stream().sorted().findFirst();
System.out.println(min :: get());
Optional max = list.stream.sorted((a, b) -> b - a).findFirst();
System.out.println(max :: get());
/*
- 按照字母顺序a - z排序
*/
Arrays.asList(“java”, “python”, “c”).stream().sorted().forEach(System.out :: println);
/*
- 按照字母的长度进行排序
*/
Arrays.asList(“java”, “python”, “c”).stream().sorted((a, b) -> a.length() - b.length()).forEach(System.out :: println);
limit
=====
-
limit方法用来截取指定长度的Stream流
-
skip方法用来丢弃指定长度的流数据,可以与limit配合实现分页
/*
- 打印出集合中20 - 30的数据
*/
Stream.iterate(x -> x + 1).limit(50)
// 跳过前20个
.skip(20)
// 输出20 - 30
.forEach(System.out :: println);
map
===
-
map用来将Stream流中的元素按照指定的函数映射成一个新的元素的Stream流
-
flatMap用来将Stream流中的每个元素转换成另一个流,然后将所有流连接成一个新的流
List list = Arrays.asList(“a, b, c”, “1, 2, 3”);
/*
- 将字符串转换为不带逗号的元素
*/
Stream mapList = list.stream().map(s -> s.replace(“,”, “”));
// abc 123
mapList.forEach(System.out :: println);
Stream flatMapList = list.stream(