Stream流
生活描述导入
stream流就像工厂流水线,就拿我们最爱吃的薯片来说,首先人工加工太麻烦惹,因此考略用机器自动化
,首先先给土豆泡个澡,在搓个灰,然后要切片,再油炸,调味,最后装袋,finish!
可见整个过程异常流畅,流水线在我们java中也有,就是今天要说的stream流了。
1. stream 流概述
1.JDK 1.8 版本及其以上支持!!!
2.利用流水线思想对于集合,数组数据进行处理和操作。涉及到数据筛选,排序,转换类型,限制个数,最终处理....
3. 并且在处理数据的过程中,对于数据的原始空间没有任何的修改,不影响原始数据。
Stream 流应用展示(超赞的!)
import java.util.ArrayList;
import java.util.Comparator;
public class Demo01 {
public static void main(String[] args) {
// 定义一个数组
ArrayList<String> list = new ArrayList<>();
list.add("卫龙辣条");
list.add("乐事薯片");
list.add("娃哈哈AD钙奶");
list.add("浪味仙");
list.add("旺仔牛奶");
list.add("喜之郎果冻");
list.add("不二家棒棒糖");
list.add("波力海苔");
list.add("大白兔奶糖");
list.add("双汇王中王");
list.add("牛肉干");
System.out.println();
// 当前集合对象调用 stream() 直接获取对应集合存储元素的 Stream 流对象
list.stream()
//俗称【掐头】,删去前list中前两个数据
.skip(2)
// 俗称【去尾】, 保留6个数据,从第六个开始,后面的数据都不要惹!
.limit(6)
// 判断过滤当前 Stream 流可以保存的数据条件,满足条件保留,不满足条件移除
.filter(s -> s.length() > 4)
// 对当前 Stream 流存储的进行排序操作
.sorted(Comparator.comparing(String::length))
// 针对于当前 Stream 存储元素的处置方法,展示效果
.forEach(System.out::println);
}
}
小结:如果用普通方法,则代码看着不够简洁,繁琐。
3. Stream流相关方法
再强调一下 Stream 流是开辟了一份新数据,不是对原数据操作!!!
原数据好好的,但我们通过 stream 流得到自己想要的数据。
3.1 stream大多处理集合与数组【起始方法】
// 集合对象
Stream<T> stream();
集合对象调用可以直接获取对应当前集合存储元素的 Stream 流对象。
// 数组
Stream<T> Arrays.Stream(T[] t);
利用 Arrays 工具类对当前需要按照 Stream 流方式操作的数据进行转换操作,根据当前数组的数据类型和数据存储情况,返回一个对应的 Stream 流对象
3.2 Stream 处理数据的【中间方法】
Stream<T> skip(long n);
限制跳过当前 Stream 流对应元素的个数,【掐头】
Stream<T> limit(long n);
限制当前 Stream 对应的元素总个数,【去尾】
Stream<T> sorted();
对当前 Stream 流存储的进行排序操作,要求元素有自然顺序或者遵从 Comparable 接口,默认【升序】
Stream<T> sorted(Comparator<? super T> com);
对当前 Stream 流存储的进行排序操作,排序规则由 Comparator 函数式接口规范
Stream<T> filter(Predicate<? super T> pre);
判断过滤当前 Stream 流可以保存的数据条件,满足条件保留,不满足条件移除,过滤规则由 Predicate 接口约束
Stream<T> distinct();
当前 Stream 流中对应的所有元素去重擦操作
Stream<R> map(Function<T, R> fun);
当前 Stream 存储的数据情况转换为 Function 函数式接口要求的返回值类型,完成类型转换操作。
3.3 Stream 处理数据的【最终方法/终止方法】
终止方法,stream流自动关闭,对应的 Stream 占用空间资源会被 JVM 收回
long count();
返回当前 Stream 流对应的数据元素个数,为终止方法。
void forEach(Consumer<? super T> con);
针对于当前 Stream 存储元素的处置方法,为终止方法。
<R, A> R collect(Collector<? super T, A, R> collector);
Stream 流对应的元素存储内容,转换为用户要求的 集合对象。终止方法
常用:
Collectors.toList() 目标存储集合类型为 List 集合
Collectors.toSet() 目标存储集合类型为 Set 集合
Object[] toArray();
Stream 流存储的元素内容转换为 Object 类型数组返回
4. 部分方法代码展示
4.1 skip 和 limit【掐头去尾】
list.stream()
.skip(2) // 跳过当前 Stream 流对应元素的前两个元素
.limit(8) // 仅保留当前 Stream 流当前的八个元素
.forEach(System.out::println);// 展示得到数据
4.2 sorted【排序】
/*
源码分析:
Stream<T> sorted(Comparator<? super T> comparator);
@FunctionalInterface
public interface Comparator<T> {
int compare(T o1, T o2);
}
*/
list.stream()
.sorted((p1, p2) -> p2.getAge() - p1.getAge())
.forEach(System.out::println);
4.3 filter 【过滤】
/*
源码分析:
Stream<T> filter(Predicate<? super T> predicate);
@FunctionalInterface
public interface Predicate<T> {
boolean test(T t);
}
*/
list.stream()
.filter(s -> s.length() >= 4)
.distinct()
.forEach(System.out::println);
4.4 map【转换类型】
/*
<R> Stream<R> map(Function<? super T, ? extends R> mapper);
Stream map 方法一般都是通过方法引用引入其他已经完成的功能模块来提升代码效率
在 map 方法中使用 Lambda 完成类型转换,代码效率较低。
*/
// list 获取自己存储元素的 stream流对象
Stream<Person> stream = list.stream();
// 调用 map 方法
Stream<String> stringStream = stream.map(s -> s.toString());
// 效果展示
stringStream.forEach(System.out::println);
4.5 count 【计数】
// list 获取自己存储元素的 stream流对象
Stream<String> stream = list.stream();
long count = stream
.skip(2) // 掐头
.limit(20) // 去尾
.skip(5) // 掐头
.count(); // 计数
/*
异常信息
stream has already been operated upon or closed
提示告知当前 Stream 已经被关闭!
*/
stream.forEach(System.out::println);
System.out.println(count);
4.6 collect [转换]
// Stream 流数据内容转 List 集合
List<String> list1 = list
.stream() // list 获取自己存储元素的 stream流对象
.distinct() // 去重
.collect(Collectors.toList()); // Stream 流对应的元素存储内容,转换为用户要求
// Stream 流数据内容转 Set 集合
Set<String> set = list.stream().skip(2).limit(20).collect(Collectors.toSet());
5. 总结
stream 流真的很好用,以后工作中也用的多,大家一定要理解原理 与 lambda 表达式的应用有一定的关联性,lambda在我上一篇文章中有介绍。
感谢各路客官收看!