云栖号资讯:【点击查看更多行业资讯】
在这里您可以找到不同行业的第一手的上云资讯,还在等什么,快来!
相信Java8的Stream 大家都已听说过了,但是可能大家不会用或者用的不熟,文章将带大家从零开始使用,循序渐进,带你走向Stream的巅峰。
操作符
什么是操作符呢?操作符就是对数据进行的一种处理工作,一道加工程序;就好像工厂的工人对流水线上的产品进行一道加工程序一样。
Stream的操作符大体上分为两种:中间操作符和终止操作符
中间操作符
对于数据流来说,中间操作符在执行制定处理程序后,数据流依然可以传递给下一级的操作符。
中间操作符包含8种(排除了parallel,sequential,这两个操作并不涉及到对数据流的加工操作):
map(mapToInt,mapToLong,mapToDouble) 转换操作符,把比如A->B,这里默认提供了转int,long,double的操作符。
flatmap(flatmapToInt,flatmapToLong,flatmapToDouble) 拍平操作比如把 int[]{2,3,4} 拍平 变成 2,3,4 也就是从原来的一个数据变成了3个数据,这里默认提供了拍平成int,long,double的操作符。
limit 限流操作,比如数据流中有10个 我只要出前3个就可以使用。
distint 去重操作,对重复元素去重,底层使用了equals方法。
filter 过滤操作,把不想要的数据过滤。
peek 挑出操作,如果想对数据进行某些操作,如:读取、编辑修改等。
skip 跳过操作,跳过某些元素。
sorted(unordered) 排序操作,对元素排序,前提是实现Comparable接口,当然也可以自定义比较器。
终止操作符
数据经过中间加工操作,就轮到终止操作符上场了;终止操作符就是用来对数据进行收集或者消费的,数据到了终止操作这里就不会向下流动了,终止操作符只能使用一次。
collect 收集操作,将所有数据收集起来,这个操作非常重要,官方的提供的Collectors 提供了非常多收集器,可以说Stream 的核心在于Collectors。
count 统计操作,统计最终的数据个数。
findFirst、findAny 查找操作,查找第一个、查找任何一个 返回的类型为Optional。
noneMatch、allMatch、anyMatch 匹配操作,数据流中是否存在符合条件的元素 返回值为bool 值。
min、max 最值操作,需要自定义比较器,返回数据流中最大最小的值。
reduce 规约操作,将整个数据流的值规约为一个值,count、min、max底层就是使用reduce。
forEach、forEachOrdered 遍历操作,这里就是对最终的数据进行消费了。
toArray 数组操作,将数据流的元素转换成数组。
这里只介绍了Stream,并没有涉及到IntStream、LongStream、DoubleStream,这三个流实现了一些特有的操作符,我将在后续文章中介绍到。
说了这么多,只介绍这些操作符还远远不够;俗话说,实践出真知。那么,Let‘s go。
代码演练
Stream 的一系列操作必须要使用终止操作,否者整个数据流是不会流动起来的,即处理操作不会执行。
map,可以看到 map 操作符要求输入一个Function的函数是接口实例,功能是将T类型转换成R类型的。
map操作将原来的单词 转换成了每个单的长度,利用了String自身的length()方法,该方法返回类型为int。这里我直接使用了lambda表达式,关于lambda表达式 还请读者们自行了解吧。
public class Main {
public static void main(String[] args) {
Stream.of("apple","banana","orange","waltermaleon","grape")
.map(e->e.length()) //转成单词的长度 int
.forEach(e->System.out.println(e)); //输出
}
}
当然也可以这样,这里使用了成员函数引用,为了便于读者们理解,后续的例子中将使用lambda表达式而非函数引用。
public class Main {
public static void main(String[] args) {
Stream.of("apple","banana","orange","waltermaleon","grape")
.map(String::length) //转成单词的长度 int
.forEach(System.out::println);
}
}
结果如图:
public class Main {
public static void main(String[] args) {
Stream.of("apple", "banana", "orange", "waltermaleon", "grape")
.mapToInt(e -> e.length()) //转成int
.forEach(e -> System.out.println(e));
}
}
mapToInt如图:
public class Main {
public static void main(String[] args) {
Stream.of("apple", "banana", "orange", "waltermaleon", "grape")
.mapToLong(e -> e.length()) //转成long ,本质上是int 但是存在类型自动转换
.forEach(e -> System.out.println(e));
}
}
mapToLong 如图:
public class Main {
public static void main(String[] args) {
Stream.of("apple", "banana", "orange", "waltermaleon", "grape")
.mapToDouble(e -> e.length()) //转成Double ,自动类型转换成Double
.forEach(e -> System.out.println(e));
}
}
public class Main {
public static void main(String[] args) {
Stream.of("a-b-c-d","e-f-i-g-h")
.flatMap(e->Stream.of(e.split("-")))
.forEach(e->System.out.println(e));
}
}
flatmap 如图:
public class Main {
public static void main(String[] args) {
Stream.of(1,2,3,4,5,6)
.limit(3) //限制三个
.forEach(e->System.out.println(e)); //将输出 前三个 1,2,3
}
}
limit如图:
public class Main {
public static void main(String[] args) {
Stream.of(1,2,3,1,2,5,6,7,8,0,0,1,2,3,1)
.distinct() //去重
.forEach(e->System.out.println(e));
}
}
distinct 如图:
public class Main {
public static void main(String[] args) {
Stream.of(1,2,3,1,2,5,6,7,8,0,0,1,2,3,1)
.filter(e->e>=5) //过滤小于5的
.forEach(e->System.out.println(e));
}
}
public class Main {
public static void main(String[] args) {
User w = new User("w",10);
User x = new User("x",11);
User y = new User("y",12);
Stream.of(w,x,y)
.peek(e->{e.setName(e.getAge()+e.getName());}) //重新设置名字 变成 年龄+名字
.forEach(e->System.out.println(e.toString()));
}
static class User {
private String name;
private int age;
public User(String name, int age) {
this.name = name;
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
@Override
public String toString() {
return "User{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
}
}
public class Main {
public static void main(String[] args) {
Stream.of(1,2,3,4,5,6,7,8,9)
.skip(4) //跳过前四个
.forEach(e->System.out.println(e)); //输出的结果应该只有5,6,7,8,9
}
}
skip 如图:
public class Main {
public static void main(String[] args) {
Stream.of(2,1,3,6,4,9,6,8,0)
.sorted()
.forEach(e->System.out.println(e));
}
}
public class Main {
public static void main(String[] args) {
User x = new User("x",11);
User y = new User("y",12);
User w = new User("w",10);
Stream.of(w,x,y)
.sorted((e1,e2)->e1.age>e2.age?1:e1.age==e2.age?0:-1)
.forEach(e->System.out.println(e.toString()));
}
static class User {
private String name;
private int age;
public User(String name, int age) {
this.name = name;
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
@Override
public String toString() {
return "User{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
}
}
public class Main {
public static void main(String[] args) {
Stream.of("apple", "banana", "orange", "waltermaleon", "grape")
.collect(Collectors.toSet()) //set 容器
.forEach(e -> System.out.println(e));
}
}
咦?,不是说终止操作符只能使用一次吗,为什么这里调用了forEach 呢?
forEach不仅仅是是Stream 中得操作符还是各种集合中得一个语法糖,不信咋们试试。
public class Main {
public static void main(String[] args) {
Set<String> stringSet = Stream.of("apple", "banana", "orange", "waltermaleon", "grape")
.collect(Collectors.toSet()); //收集的结果就是set
stringSet.forEach(e->System.out.println(e)); set的语法糖forEach
}
![3825B37B_D04B_49ac_A0B2_CB08DA5D5616](https://yqfile.alicdn.com/df18d416a1666dc1d1d9511602a16c2d3e7ea352.png
public class Main {
public static void main(String[] args) {
long count = Stream.of("apple", "banana", "orange", "waltermaleon", "grape")
.count();
System.out.println(count);
}
}
public class FindFirst {
public static void main(String[] args) {
Optional<String> stringOptional = Stream.of("apple", "banana", "orange", "waltermaleon", "grape")
.findFirst();
stringOptional.ifPresent(e->System.out.println(e));
}
}
public class FindAny {
public static void main(String[] args) {
Optional<String> stringOptional = Stream.of("apple", "banana", "orange", "waltermaleon", "grape")
.parallel()
.findAny(); //在并行流下每次返回的结果可能一样也可能不一样
stringOptional.ifPresent(e->System.out.println(e));
}
}
这里 的作用是是判断数据流中 一个都没有与aa 相等元素 ,但是流中存在 aa ,所以最终结果应该是false。
public class NoneMatch {
public static void main(String[] args) {
boolean result = Stream.of("aa","bb","cc","aa")
.noneMatch(e->e.equals("aa"));
System.out.println(result);
}
}
public class Main {
public static void main(String[] args) {
Optional<Integer> integerOptional = Stream.of(0,9,8,4,5,6,-1)
.min((e1,e2)->e1.compareTo(e2));
integerOptional.ifPresent(e->System.out.println(e));
}
public class Main {
public static void main(String[] args) {
Optional<Integer> integerOptional = Stream.of(0,9,8,4,5,6,-1)
.max((e1,e2)->e1.compareTo(e2));
integerOptional.ifPresent(e->System.out.println(e));
}
}
public class Main {
public static void main(String[] args) {
int sum = Stream.of(0,9,8,4,5,6,-1)
.reduce(0,(e1,e2)->e1+e2);
System.out.println(sum);
}
}
public class ForEachOrdered {
public static void main(String[] args) {
Stream.of(0,2,6,5,4,9,8,-1)
.parallel()
.forEachOrdered(e->{
System.out.println(Thread.currentThread().getName()+": "+e);});
}
}
public class ToArray {
public static void main(String[] args) {
Object[] objects=Stream.of(0,2,6,5,4,9,8,-1)
.toArray();
for (int i = 0; i < objects.length; i++) {
System.out.println(objects[i]);
}
}
}
【云栖号在线课堂】每天都有产品技术专家分享!
课程地址:https://yqh.aliyun.com/zhibo立即加入社群,与专家面对面,及时了解课程最新动态!
【云栖号在线课堂 社群】https://c.tb.cn/F3.Z8gvnK
原文发布时间:2020-07-03
本文作者:litesky
本文来自:“互联网架构师”,了解相关信息可以关注“互联网架构师”
来源:oschina
链接:https://my.oschina.net/u/4400708/blog/4334778