流式思想:像生产流水线一样,一个操作接一个操作。

1-1.流式思想的概述

循环遍历的弊端

Java 8的Lambda让我们可以更加专注于做什么(What ),而不是怎么做(How),这点此前已经结合内部类进行了对比说明。现在,我们仔细体会一下for循环的代码,可以发现∶

. for循环的语法就是"怎么做”
. for循环的循环体才是“做什么”

为什么使用循环?因为要进行遍历。但循环是遍历的唯一方式吗?遍历是指每一个元素逐一进行处理,而并不是从第一个到最后一个顺次处理的循环。前者是目的,后者是方式。

使用stream流的方式,遍历集合,对集合中的数据进行过滤
stream流是JDK1.8之后出现的
关注的是做什么,而不是怎么做

整体来看,流式思想类似于工厂车间的“生产流水线”。

Stream(流)是一个来自数据源的元素队列
元素是特定类型的对象,形成一个队列。Java中的Stream并不会存储元素,而是按需计算。
数据源是流的来源。可以是集合,数组等。

和以前的Collection操作不同,Stream操作还有两个基础的特征∶
Pipelining:中间操作都会返回流对象本身。这样多个操作可以串联成一个管道,如同流式风格( fluentstyle )。这样做可以对操作进行优化,比如延迟执行(laziness)和短路(short-circuiting)。
内部迭代︰以前对集合遍历都是通过lIterator或者增强for的方式,显式的在集合外部进行迭代,这叫做外部迭代。Stream提供了内部迭代的方式,流可以直接调用遍历方法。

1-3.获取流

java.util.stream.Stream<T>是Java8新加入的最常用的流接口。(这并不是一个函数式接口。)
获取一个流非常简单,有以下几种常用的方式:
所有的Collection 集合都可以通过stream默认方法获取流;
Stream接口的静态方法of可以获取数组对应的流。

default stream<E> stream
stream接口的静态方法of可以获取数组对应的流。
static <r> Stream<T> of (T... values)
参数是一个可变参数,那么我们就可以传递一个数组

流模型的操作很丰富,这里介绍一些常用的API。这些方法可以被分成两种:
·终结方法:返回值类型不再是Stream接口自身类型的方法,因此不再支持类似stringBuilder那样的链式调用。在这里,终结方法包括count和forEach 方法。
·延迟方法:返回值类型仍然是Stream:接口自身类型的方法,因此支持链式调用。(除了终结方法外,其余方法均为延迟方法。)

1-4.Strearr流中的常用方法_forEach
void forEach( consumer<? super r> action );
该方法接收一个consumer接口函数,会将每一个流元素交给该函数进行处理。
Consumer接口是一个消费型的函数式接口,可以传递Lambda表达式,消费数据
简单记:
forEach方法,用来遍历流中的数据
是一个终结方法,遍历之后就不能继续调用Stream流中的其他方法

1-5.Streami流中的常用方法_filter

streami流中的常用方法_filter:用于对stream流中的数据进行过滤
Stream<T> filter( Predicate<? super T> predicate);
filter方法的参数Predicate是一个函数式接口,所以可以传递Lambda表达式,对数据进行过滤
predicate中的抽象方法:
boolean test(T t);

注意:

Stream流属于管道流,只能被消费(使用)一次
第—个Stream流调用完毕方法,数据就会流转到下一个Stream上
而这时第一个Stream流已经使用完毕,就会关闭了
所以第一个Streami流就不能再调用方法了.

1-6.stream流中的常用方法_map

如果需要将流中的元素映射到另一个流中,可以使用map方法.
<R> Stream<R> map(Function<? super T, ? extends R> mapper);
该接口需要一个Function函数式接口参数,可以将当前流中的T类型数据转换为另一种R类型的流。
Function中的抽象方法:
RappLy(T t);

1-7.stream流中的常用方法_count:

stream流中的常用方法_count:用于统计stream流中元素的个数
long count( );
count方法是一个终结方法,返回值是一个long类型的整数
所以不能再继续调用stream流中的其他方法了

1-8.Stream流中的常用方法_limit

Stream流中的常用方法_limit:用于截取流中的元素
Limit方法可以对流进行截取,只取用前n个。
Stream<T> limit(long maxsize);
参数是一个long型,如果集合当前长度大于参数则进行截取;否则不进行操作
limit方法是一个延迟方法,只是对流中的元素进行截取,返回的是一个新的流,所以可以继续调用Stream流中的其他方法

1-9.Stream流中的常用方法_skip

Stream流中的常用方法_skip:用于跳过元素
如果希望跳过前几个元素,可以使用skip芳法获取一个截取之后的新流:
Stream<T> skip(long n);
如果流的当前长度大于n,则跳过前n个﹔否则将会得到一个长度为0的空流。

1-10.Stream流中的常用方法_concat

Stream流中的常用方法_concat:用于把流组合到一起
如果有两个流,希望合并成为一个流,那么可以使用stream接口的静态方法concat
static <T〉Stream<T> concat(Stream<? extends T> a,Stream<? extends T> b)

2-1.方法引用的基本介绍

双冒::为引用运算符,而它所在的表达式被称为方法引用。如果Lambda要表达的函数方案已经存在于某个方法的实现中,那么则可以通过双冒号来引用该方法作为Lambda的替代者。

例如,下列这两种写法是完全等效的:

Lambda表达式写法:s-> System.out.println(s);
方法引用写法:System.out: :println
第一种语义是指︰拿到参数之后经Lambda之手,继而传递给System.out.println方法去处理。

第二种等效写法的语义是指∶直接让system.out中的println方法来取代Lambda。两种写法的执行效果完全一样,而第二种方法引用的写法复用了已有方案,更加简洁。
注:Lambda中传递的参数一定是方法引用中的那个方法可以接收的类型,否则会抛出异常

2-2.通过对象名引用成员方法

通过对象名引用成员方法

便用前提是对象名是已经存在的,成员方法也是已经存在
就可以使用对象名来引用成员方法

2-3.通过类名引用静态成员方法

通过类名引用静态成员方法
类已经存在,静态成员方法也已经存在
就可以通过类名直接引用静态成员方法

2-4.通过super引用成员方法

如果存在继承关系,当Lambda中需要出现super调用时,也可以使用方法引用进行替代。

2-5.通过this引用成员方法

this代表当前对象,如果需要引用的方法就是当前类中的成员方法,那么可以使用"this成员方法"”的格式来使用方法引用。

2-6.类的构造器的引用

由于构造器的名称与类名完全一样,并不固定。所以构造器引用使用类名称::new的格式表示。

2-7.数组的构造器的引用

数组也是object的子类对象,所以同样具有构造器,只是语法稍有不同。

守着安静的沙漠,等待着花开...