序
流式计算 链式编程
1.包位置
java.util.stream
2.简介
概要:
集合/序列的流式高效计算;
描述:
一个数据渠道,用于操作数据源(集合、数组等)所生成的元素序列;
一种高效且易于使用的处理数据的方式
//直观对比
List<Integer> list = Arrays.asList(2, 3, 5, 4, 1, 8, 10, 9, 7, 6);
// 传统方式
for (Integer num : list) {
if (num > 5)
System.out.println(num);
}
// Stream方式
list.stream()
.filter((e) -> e > 5)
.forEach(System.out::println);
3.内部逻辑
- 创建 Stream:从一个数据源(如集合、数组)中获取一个流
- 中间操作:一个或多个中间操作,对数据源的数据进行处理
- 终止操作:执行中间操作链,并产生结果
3.1.创建 Stream
3.1.1. 集合 创建
Collection 接口中,提供了获取流的方法
- default Stream stream() : 返回一个顺序流
- default Stream parallelStream() : 返回一个并行流
List<String> list = new ArrayList<>();
Stream<String> stream = list.stream(); //获取一个顺序流
Stream<String> parallelStream = list.parallelStream(); //获取一个并行流
3.1.2. 数组 创建
Arrays
的静态方法 stream()
提供了获取流的方法
- static Stream stream(T[] array): 返回一个流
Integer[] nums = new Integer[8];
Stream<Integer> stream = Arrays.stream(nums);
3.1.3. 值 创建
静态方法 Stream.of(),可以接收任意数量的参数
- public static Stream of(T… values) : 返回一个流
Stream<Integer> stream = Stream.of(1,2,3,4,5);
3.1.4. 函数 创建
静态方法 Stream.iterate() 和Stream.generate(), 创建无限流
- public static Stream iterate(final T seed, final UnaryOperator f)
- public static Stream generate(Supplier s) :
//起始值: 1
//函数:(x) -> x + 1
//控制台一直在输出数字,不会停 (无限)
Stream.iterate(1, (x) -> x + 1).forEach(System.out::println);
//参数:Supplier实例
//控制台一直在输出大于等于0小于1的随机数
Stream.generate(() -> Math.random()).forEach(System.out::println);
3.2.中间操作
流水线式处理,【惰性求值】
惰性求值:Stream 操作是延迟执行的。只有等到需要结果的时候才执行操作。
特点:Stream 不改变源对象。返回一个新的结果Stream(链式编程)。
List<Integer> list = Arrays.asList(1, 2, 3, 4, 5, 6);
//输出
//4
//5
//6
list.stream()
.filter(x -> x > 3)// 筛选出大于3的元素
.forEach(System.out::println);
//list [1, 2, 3, 4, 5, 6]
//源对象 不变
System.out.println(list);
主要处理如下:
- 筛选
- 切割
- 映射
- 排序
3.2.1. 筛选
- filter(Predicate p): 过滤
- distinct(): 去重
List<Integer> list = Arrays.asList(2, 3, 5, 4, 1, 8, 10, 9, 7, 6);
//过滤出数据中需要的数据
list.stream()
.filter((e) -> e > 5)
.forEach(System.out::println);
//去除数据中的重复
list.stream()
.distinct()
.forEach(System.out::println);
3.2.2. 切割
- limit(long maxSize): 使元素不超过给定数量
- skip(long n): 去掉了前 n 个元素
List<Integer> list = Arrays.asList(1, 2, 3, 4, 5, 6);
//只保留前3个元素
list.stream()
.limit(3)
.forEach(System.out::println);
//去掉前3个元素
list.stream()
.skip(3)
.forEach(System.out::println);
3.2.3. 映射
- map(Function f) : 返回映射的结果
- mapToDouble(ToDoubleFunction f): 返回映射的结果,Double类型
- mapToInt(ToIntFunction f): 返回映射的结果,Int类型
- mapToLong(ToLongFunction f): 返回映射的结果,Long类型
- flatMap(Function f): 流中的每个元素映射成一个流
List<Integer> list = Arrays.asList(1, 2, 3);
list.stream()
.map(x -> x*x)
.forEach(System.out::println);
list.stream()
.mapToDouble(x -> x+0.1)
.forEach(System.out::println);
List<String> list = Arrays.asList("a", "b", "c");
//输出
//a
//b
//c
list.stream()
.flatMap(TestStreamAPI::stringToStream)
.forEach(System.out::println);
public static Stream<Character> stringToStream(String str) {
List<Character> list = new ArrayList<>();
char[] charArray = str.toCharArray();
for (char c : charArray) {
list.add(c);
}
return list.stream();
}
3.2.4. 排序
- sorted(): 自然顺序排序
- sorted(Comparator comp): 按比较器顺序排序
List<String> list = Arrays.asList("d", "a", "c");
//输出
//a
//b
//c
list.stream()
.sorted()
.forEach(System.out::println);
//输出
//c
//b
//a
list.stream()
.sorted((x,y) -> -x.compareTo(y))
.forEach(System.out::println);
3.3.终止操作
终止操作会从流的中间操作流水线生成结果。其结果可以是任何不是流的值。
具体操作有:
- 查找与匹配
- 归约
- 收集
3.3.1 查找与匹配【常用】
- allMatch(Predicate p) : 检查是否匹配所有元素
- anyMatch(Predicate p): 检查是否至少匹配一个元素
- noneMatch(Predicate p) : 检查是否没有匹配所有元素
- findFirst() : 返回第一个元素
- findAny() : 返回当前流中的任意元素
- count() : 返回流中元素总数
- max(Comparator c) : 返回流中最大值
- min(Comparator c) : 返回流中最小值
- forEach(Consumer c): 内部迭代(使用 Collection 接口需要用户去做迭代,称为外部迭代。相反, Stream API 使用内部迭代)
List<Integer> list = Arrays.asList(10, 5, 7, 3);
//是否全部元素都大于2
//返回:true
list.stream()
.allMatch(x -> x > 2);
//val = 10
Optional<Integer> first = list.stream().findFirst();
Integer val = first.get();
//val = 3
first = list.stream().min(Integer::compareTo);
val = first.get();
//val = 10
first = list.stream().max(Integer::compareTo);
val = first.get();
3.3.2. 归约
- reduce(T iden, BinaryOperator b): 将流中元素循环迭代,得到一个T类型的值
- reduce(BinaryOperator b): 将流中元素循环迭代,得到一个Optional类型的值
List<Integer> list = Arrays.asList(10, 5, 7, 3);
//累加 2+10+5+7+3
//返回 27
list.stream()
.reduce(2, Integer::sum);
//累加 10+5+7+3
//返回 25
list.stream()
.reduce(Integer::sum);
3.3.3. 收集
- collect(Collector c):将流转换为其他形式
List<Integer> list = Arrays.asList(10, 5, 7, 3);
// 将流中元素收集到List中
// 输出[10, 5, 7, 3]
list.stream()
.collect(Collectors.toList());
// 将流中元素收集到Set中
// 输出[3, 5, 7, 10]
list.stream()
.collect(Collectors.toSet());
// 计算出流中的元素个数
// 输出4
list.stream()
.collect(Collectors.counting());
// 计算流中Integer类型数据的总和
// 输出25
list.stream()
.collect(Collectors.summingInt(x -> x));
3.4. 并行流
多线程执行操作
3.4.1. 包
java.util.Collection<E>
- default Stream stream() : 返回串行流
- default Stream parallelStream() : 返回并行流
//串行流和并行流差别就是单线程和多线程的执行
//执行时间影响因素:电脑环境,数据量等
List<Integer> list = new ArrayList<>();
// 将10000-1存入list中
for (int i = 10000; i >= 1; i--) {
list.add(i);
}
list.stream()// 获取串行流
.sorted()// 按自然排序,即按数字从小到大排序
.count();// count()是终止操作,有终止操作才会执行中间操作sorted()
list.parallelStream()// 获取并行流
.sorted()// 按自然排序,即按数字从小到大排序
.count();// count()是终止操作,有终止操作才会执行中间操作sorted()