Stream流
流式思想概述
Stream流式思想处理数据的方式:
让代码像流水线一样, 一步一步的对数据进行处理, 得到最终的结果
流也可以看作是一个容器, 里面可以装很多元素, 形成元素流
流相比于集合的2个优点:
1. Pipelining(管道特性)
Stream流对象的一些方法调用完毕后, 会返回新的Stream流对象, 类型相同, 可链式调用, 类似于"管道"
2. 内部迭代特性:
集合遍历通过 Iterator 或者 增强for, 显式的在集合外部进行迭代, 这叫做外部迭代
Stream提供了内部迭代的方法 forEach(), 可以直接调用遍历方法
使用Stream流的3个步骤:
1. 获取数据源 (集合, 数组)
2. 数据转换
3. 获得结果
2种获取Stream流的方式
获取Stream流对象的2种方式:
1. 利用Collection接口中的默认方法 default Stream<E> stream() 方法: 集合转Stream对象
2. 利用Stream接口中的静态方法 static<T> Stream<T> of(T... values): 数组转Stream对象
java.util.Collection<E>接口:
// 默认方法
default Stream<E> stream(): 将"集合"转换为Stream对象
java.util.stream.Stream<T>接口: 管道接口, 泛型为流中元素的类型
// 静态方法
static<T> Stream<T> of(T... values): 将"数组"转换为Stream对象
Stream API
方法分类
延迟方法: (具有延迟执行的特性)
返回值类型 是 Stream接口自身类型的方法, 支持链式调用
filter(): 过滤
map(): 映射/转换
limit(): 截取
skip(): 跳过
终结方法:
返回值类型 不是 Stream接口自身类型的方法, 不支持链式调用
forEach(): 遍历
count(): 统计
注意:
除了终结方法外, 其余方法均为延迟方法
ArrayList().filter(...).map(...).limit(...).skip(...).forEach(...);
Stream.of(1,2,3).filter(...).map(...).limit(...).skip(...).count();
java.util.stream.Stream<T>接口: 管道接口
// 抽象方法
void forEach(Consumer<? super T> action): 遍历流中的元素进行逐一消费. 并不保证元素的逐一消费动作在流中是被有序执行的
静态方法concat()合并两个流
java.util.stream.Stream<T>接口: 管道接口
// 静态方法
static <T> Stream<T> concat(Stream<? extends T> a, Stream<? extends T> b):
合并两个流的元素, 变成一个新的流. 两个流中的元素类型必须相同, 或有共同的父类
方法引用
方法引用: Method Reference
如果Lambda表达式仅仅是调用一个已经存在的方法, 那就可以通过方法引用来替代Lambda表达式
作用: 简化Lambda表达式
:: 方法引用运算符, 它所在的表达式被称为方法引用
Lambda表达式写法:
(String s) -> System.out.println(s)
参数传递给System.out.println()方法去打印
方法引用写法:
System.out::println
用System.out.println()方法中代码, 来作为Lambda中重写方法的实现方式
注意:
Lambda 中 传递的参数 一定是方法引用中 的那个方法可以接收的类型,否则会抛出异常
方法引用能简化以下场景: (方法名后不要写小括号)
1. 通过对象名引用成员方法 对象名::成员方法名 System.out::println
2. 通过类名引用静态方法 类名::静态方法名 i -> Math.abs(i) Math::abs
3. 通过super引用父类成员方法 super::父类方法名 ()->super.eat(); super::eat
4. 通过this引用本类成员方法 this::本类方法名 ()->this.eat(); this::eat
5. 引用某个类的构造方法 类名::new name->new Person(name) Person::new
6. 引用创建数组的方法 数据类型[]::new length->new int[length]; int[]::new
|
|