在Java 8中,得益于Lambda所带来的函数式编程,引入了一个全新的Stream概念,用于解决已有集合类库既有的弊端。
Java 8的Lambda让我们可以更加专注于做什么(What),而不是怎么做(How),这点此前已经结合内部类进行 了对比说明。现在,我们仔细体会一下上例代码,可以发现:
for循环的语法就是“怎么做” for循环的循环体才是“做什么”
为什么使用循环?因为要进行遍历。但循环是遍历的唯一方式吗?遍历是指每一个元素逐一进行处理,而并不是从
第一个到最后一个顺次处理的循环。前者是目的,后者是方式。
试想一下,如果希望对集合中的元素进行筛选过滤: 1. 将集合A根据条件一过滤为子集B;
2. 然后再根据条件二过滤为子集C。
每当我们需要对集合中的元素进行操作的时候,总是需要进行循环、循环、再循环。这是理所当然的么?不是。循环是做事情的方式,而不是目的。另一方面,使用线性循环就意味着只能遍历一次。如果希望再次遍历,只能再使
用另一个循环从头开始。
“Stream流”其实是一个集合元素的函数模型,它并不是集合,也不是数据结构,其本身并不存储任何 元素(或其地址值)。
Stream(流)是一个来自数据源的元素队列元素是特定类型的对象,形成一个队列。 Java中的Stream并不会存储元素,而是按需计算。
数据源 流的来源。 可以是集合,数组 等。 和以前的Collection操作不同, Stream操作还有两个基础的特征:
Pipelining: 中间操作都会返回流对象本身。 这样多个操作可以串联成一个管道, 如同流式风格(fluent style)。 这样做可以对操作进行优化, 比如延迟执行(laziness)和短路( short-circuiting)。
内部迭代: 以前对集合遍历都是通过Iterator或者增强for的方式, 显式的在集合外部进行迭代, 这叫做外部迭 代。 Stream提供了内部迭代的方式,流可以直接调用遍历方法。
当使用一个流的时候,通常包括三个基本步骤:获取一个数据源(source)→ 数据转换→执行操作获取想要的结 果,每次转换原有 Stream 对象不改变,返回一个新的 Stream 对象(可以有多次转换),这就允许对其操作可以 像链条一样排列,变成一个管道。
使用传统的方式,遍历集合,对集合中的数据进行过滤
思考:
传统方式操作集合,有什么弊端?
03_使用Stream流的方式,遍历集合,对集合中的数据进行过滤
04_流式思想概述
Stream流会不会存储真正的元数据?
不会
Stream流的数据来源?
集合,数组;
05_两种获取Stream流的方式
通过Collection集合获取?
Stream stream()
Stream的静态方法获取方式?
Stream of()
06_Stream流中的常用方法_forEach
什么是延迟方法?
调用该方法后,返回值还是Stream流对象的方法;
什么是终结方法?
调用该方法后,返回值不再是Stream流对象的方法;
07_Stream流中的常用方法_filter
filter方法的返回值类型?
Stream;
08_Stream流的特点_只能使用一次
***
一个Stream流只能调用一次方法;
09_Stream流中的常用方法_map
map方法的返回值类型?
Stream
10_Stream流中的常用方法_count
count方法的返回值类型?
long
11_Stream流中的常用方法_limit
limit(long maxSize)方法的返回值类型?
Stream
当maxSize超过可操作的元素的个数后,会发生什么?
不会报错,返回全部元素;
12_Stream流中的常用方法_skip
skip(long n)方法的返回值类型?
Stream
当n超过可操作的元素的个数后,会发生什么?
不会报错,跳过所有元素;
13_Stream流中的常用方法_concat
扩展:
//收集到Set集合中:
Set collect(Collectors.toSet())
//收集到List集合中:
List collect(Collectors.toList())
延迟方法:
Stream filter(Predicate p);
Stream map(Function f);
Stream limit(数值);
Stream skip(数值);
static Stream concat(Stream s1,Stream s2);
终结方法:
void foreach(Consumer con);
long count();
Set collect(Collectors.toSet())
List collect(Collectors.toList())
14_练习:集合元素处理(传统方式)
15_练习:集合元素处理(Stream方式)
方法引用
:: 是什么?
引用运算符
什么是方法引用?
某个地方存在某个方法,我通过某种方式把它拿过用一用;
什么时候用方法引用?
当你写一个Lambda表达式的时候,如果该lambda表达式要完成的功能已经在某个地方,存在一个方法能完成一模一样的功能,
这个时候就可以把该方法引用过来;
Lambda的使用场景:
替代函数式接口的实现类对象
方法引用的使用场景:
用来替代lambda表达式;
17_方法引用_通过对象名引用成员方法
格式:
对象名 :: 成员方法名
18_方法引用_通过类名引用静态成员方法
格式:
类名::静态方法名;
19_方法引用_通过super引用父类的成员方法
引用成员方法的格式?
super :: 成员方法名;
20_方法引用_通过this引用本类的成员方法
格式:
this :: 成员方法名;
21_方法引用_类的构造器(构造方法)引用
格式:
构造方法名::new
22_方法引用_数组的构造器引用
格式:
数据类型[] :: new