Java 8 新特性之 --Stream
一. 简单介绍
Stream 是 Java 8 提出了的一种新的对集合对象功能的增强. 它集合 Lambda 表达式, 对集合提供了一些非常便利, 高效的操作, 使得代码具有非常高的可读性, 优雅性!! 举个例子来说, 它就像一个流水线操作, 对输入流水线的东西 (水果) 进行一系列加工处理, 最后获取到我们需要的某种特殊的水果(没有洗过的苹果).
Stream 提供了对集合的便捷化处理方式
声明式编程的思想
代码更加优雅, 简洁, 不信往下看→_→
来个例子来看看 Stream 风格
上海从今年 7 月 1 号开始, 进行了史无前例的垃圾分类, 先看个图图, 下图是上海最近流行的挎包(捂脸笑哭), 怕不怕, 哈哈.
闲话不多说, 进入正题, 现在需要将一堆垃圾 List<Garbage> garbages 分类处理.
使用了 Stream 的代码风格
- // 有一堆没分类的垃圾
- List<Garbage> garbage = new ArrayList<>();
- // 通过 Java 8 提供的流优雅的处理下, 瞧好喽
List<Garbage> 干垃圾 = garbage.stream() //1. 垃圾倒出来, 放到流水线
- .filter(x -> "挑出有害垃圾") //2. 挑出有害垃圾
- .filter(x -> "挑出可回收垃圾") //3. 挑出可回收垃圾
- .filter(x -> "挑出有害垃圾") //4. 挑出有害垃圾
- .collect(Collectors.toList()); //5. 把剩下的干垃圾装到干垃圾桶
- /** 上面是不是非常优雅呢 **/
二. Stream 的操作流程
Stream 的所有操作分为三个阶段,[创建]>> [中间操作]>> [终端操作]
1. Stream 的[创建]
方式一
- list.stream()
- // 通过 List 集合创建
- List<String> list = Arrays.asList("1", "2", "3");
- //list.stream()
- Stream<String> stream = list.stream();
方式二
- Stream.of()
- // 直接通过指定的元素创建
- Stream<String> stream = Stream.of("1", "2", "3");
- // 通过数组 Array
- String[] arrays = {
- "a", "b", "c"
- };
- Stream<String> stream = Stream.of(arrays);
- // 和上面区别不大
- Stream<String> stream1 = Arrays.stream(arrays);
其他
数值流的操作
对于基本数值型, 目前有三种对应的包装类型 Stream:
- IntStream.of(new int[]{
- 1, 2, 3
- }).forEach(System.out::println);
- IntStream.range(1, 3).forEach(System.out::println);
- IntStream.rangeClosed(1, 3).forEach(System.out::println);
2. Stream 的流水线操作[中间操作]
下面式常用的中间操作
- Stream Operation | Goal | Input
- :--:|:--:|:--:
filter | filter 方法用于通过设置的条件过滤出元素. | 条件(返回布尔值)Predicate
map | map 方法用于映射每个元素到对应的结果 | 可以是一个功能 Function
limit | limit 方法用于获取指定数量的流 | int 值
sorted | sorted 方法用于对流进行排序 | Comparator
distinct | 去除重复 | --
parallel | parallelStream 是流并行处理程序的代替方法 | --
... | ... | ...
filter 统计空字符串的个数
- List<String>strings = Arrays.asList("abc", "","bc","efg","abcd","", "jkl");
- // 获取空字符串的数量
- int count = strings.stream().filter(string -> string.isEmpty()).count()
map 使用 map 输出了元素对应的平方数
- List<Integer> numbers = Arrays.asList(3, 2, 2, 3, 7, 3, 5);
- // 获取对应的平方数
- List<Integer> squaresList = numbers.stream().map( i -> i*i).distinct().collect(Collectors.toList());
limit 使用 limit 方法打印出 10 条数据
- Random random = new Random();
- random.ints().limit(10).forEach(System.out::println);
sorted 使用 sorted 方法对输出的 10 个随机数进行排序
- Random random = new Random();
- random.ints().limit(10).sorted().forEach(System.out::println);
distinct 使用 distinct 对元素进行去重
- List<Integer> numbers = Arrays.asList(3, 2, 2, 3, 7, 3, 5);
- numbers.stream().distinct().forEach(System.out::println);
parallel 使用 parallelStream 来输出空字符串的数量
- List<String> strings = Arrays.asList("abc", "","bc","efg","abcd","", "jkl");
- // 获取空字符串的数量
- int count = strings.parallelStream().filter(string -> string.isEmpty()).count();
3. [终端操作]
Stream Operation | Goal | Input Or Output |
---|---|---|
forEach | 遍历元素 | 其他操作 |
count | 统计元素个数 | -- |
collect | 聚合操作 | -- |
forEach 遍历打印
Stream.of("a", "b", "c").forEach(System.out::println);
count 统计'a'的数量
long count = Stream.of("a", "b", "c", "a").filter(x -> "a".equals(x)).count();//2
collect 聚合
- // 1. 聚合转成 List
- List<String> list1 = stream.collect(Collectors.toList());
- List<String> list2 = stream.collect(Collectors.toCollection(ArrayList::new));
- // 2. 聚合转成 Set
- Set set1 = stream.collect(Collectors.toSet());
- Stack stack1 = stream.collect(Collectors.toCollection(Stack::new));
- // 3. 聚合转成 String
- String str = stream.collect(Collectors.joining()).toString();
- // 4. ... 其他
三. 简单说下声明式编程
小故事: 早上刚上班, 经理找到大胖说:"大胖啊, 咱们下去去聚餐, 软件园旁边有好几家不错的餐馆, 如巫山烤鱼, 海底捞, 大鸭梨, 你到大众点评调查一下, 也问问去过的同事, 看看哪家的口碑好. 我们有 14 个人, 预定一张大桌子, 然后用滴滴约 4 辆车, 每辆车坐 3~4 人, 我们会在 11 点半出发".
如果经理是程序员, 大胖是计算机, 这就是典型的命令式编程.
实际上, 现实中一般是经理对大胖说:"大胖啊, 我给你交代一件事, 咱们下午要聚餐, 你在软件园旁边找一家合适的餐馆, 我们有 14 个人, 11 点半出发". 这种就是声明式编程
1. 声明式编程最知名的就是我们都熟悉的 SQL
- SELECT stu.id, stu.name, ss.score
- FROM student stu, student_score ss
- WHERE stu.id = ss.id
- AND ss.score> 80
2. 用 Java 也来举个例子
有一个学生列表, 计算出年龄小于 18 岁的学生数量
传统命令式编程
- // 声明一个计数器, 遍历学生集合, 如果学生年龄小于 18 岁, 计数器 + 1
- int count = 0;
- Iterator<Student> iter = students.iterator();
- while(iter.hasNext()) {
- Student s = iter.next();
- if (s.getAge <18) {
- count++;
- }
- }
声明式编程
- // 过滤学生构成的流(Stream), 只把年龄小于 18 岁的留下, 然后做个统计.
- int count = students.stream()
- .filter(s -> s.getAge() < 18)
- .count();
声明式编程也是一种高度的抽象, 我只告诉你我要干什么, 至于怎么干, 我 Don't care
参考资料书 - 刘欣. 码农翻身
参考资料 1 https://mp.weixin.qq.com/s/Li6ph-nsoiGfP6gSq2p1CA
参考资料 2
来源: https://www.cnblogs.com/baijinqiang/p/11137199.html