Java Steam流处理入门
最近工作开始写java,复习一下java 的lambda,stream,Optional操作
lambda表达式
不关心名字,只关心具体操作,其实就是对匿名内部类的优化
基本格式 ()-{}
参数类型可以省略
只有一个参数,小括号可以省略
只有一个语句,大括号,分号都可以省略,如果是return ,return也要省略
stream流
概述
更方便的对集合或者数组进行链状流式操作
入门
authors.stream()
.distince() //去重
.filter((author) -> {
return auther.getAge() < 18;
}) //过滤,测试接口 年龄小于18
.forEach((author) -> {
System.out.print(author);
}) //消费性接口
常用操作
创建流
单列集合:集合对象.stream()
authors.stream()
数组:Arrays.stream(数组)或者Stream.of()
Integer[] nums = {1,2,3,4,5};
Arrays.stream(nums);
Stream.of(nums);
双列集合:转换成单列在创建
HashMap<String,String> map = new HashMap<>();
//转换成单列集合,在创建
map.entrySet().stream()
中间操作
filter:根据传入的条件进行判断过滤
authors.stream()
.distince() //去重
.filter((author) -> {
return auther.getName().length() > 1;
}) //过滤,测试接口 年龄小于18
.forEach((author) -> {
System.out.print(author);
}) //消费性接口
map:对流的元素进行计算或者转换,进行转换
authors.stream()
.distince() //去重
.map((author) -> {
return auther.getName();
}) //map转换
.forEach((name) -> {
System.out.print(name);
}) //消费性接口
distinct:去重,依赖equals方法,所以对象必须重写equals
authors.stream()
.distince() //去重
.map((author) -> {
return auther.getName();
}) //过滤,测试接口 年龄小于18
.forEach((name) -> {
System.out.print(name);
}) //消费性接口
sorted : 传入比较函数,不传就会用对象自己的实现比较方法comparable 接口
authors.stream()
.distince() //去重
.sorted((o1, o2) -> {
return o1.getAge()-o2.getAge();
}) //排序
.forEach((name) -> {
System.out.print(name);
}) //消费性接口
llimit:限制最大长度
authors.stream()
.distince() //去重
.sorted((o1, o2) -> {
return o1.getAge()-o2.getAge();
}) //排序
.limit(2)
.forEach((name) -> {
System.out.print(name);
}) //消费性接口
skip:跳过
authors.stream()
.distince() //去重
.sorted((o1, o2) -> {
return o1.getAge()-o2.getAge();
}) //排序
.skip(1)
.limit(2)
.forEach((name) -> {
System.out.print(name);
}) //消费性接口
flapMap:将一个对象转换成多个对象,多个对象平铺
authors.stream()
.distince() //去重
.flapMap((author) ->{
return author.getBooks().stream();
})
.forEach((name) -> {
System.out.print(name);
}) //消费性接口
authors.stream()
.flapMap((author) ->{
return author.getBooks().stream();
})
.flapMap((boos) ->{
return Arrays.stream(book.getCategory().split(","));
})
.distince()
.forEach((category) -> {
System.out.print(name);
}) //消费性接口
终结操作
forEach :消费型接口
authors.stream()
.flapMap((author) ->{
return author.getBooks().stream();
})
.flapMap((boos) ->{
return Arrays.stream(book.getCategory().split(","));
})
.distince()
.forEach((category) -> {
System.out.print(name);
}) //消费性接口
count:统计数目
authors.stream()
.flapMap((author) ->{
return author.getBooks().stream();
})
.flapMap((boos) ->{
return Arrays.stream(book.getCategory().split(","));
})
.distince()
.count()
max/min:获取最值
authors.stream()
.flapMap((author) ->{
return author.getBooks().stream();
})
.map((boos) ->{
return boos.getScore();
})
.max((o1, o2) -> {
return o1 - o2;
});
collect:收集器
authors.stream()
.flapMap((author) ->{
return author.getBooks().stream();
})
.map((boos) ->{
return boos.getScore();
})
.collect(Collectors.toList());
authors.stream()
.flapMap((author) ->{
return author.getBooks().stream();
})
.map((boos) ->{
return boos.getScore();
})
.collect(Collectors.toSet());
转map (使用多),传入两个参数,一个转key,注意key不为空,不可以重复,一个转value
authors.stream()
.collect(Collectors.toMap((author) ->{
return author.getName();
}, (author) -> {
return author.getBooks();
}));
- 查找匹配:
anyMatch :任意一个匹配,返回true
authors.stream()
.anyMatch((author) ->{
return author.getAge() > 29;
})
noneMatch 一个都匹配不上,为true
allMatch:全部匹配上
authors.stream()
.allMatch((author) ->{
return author.getAge() > 29;
})
findAny:随机获取的,无法保证获取哪一个,可能为空,optional对象接受
authors.stream()
.findAny()
findFirst:获取第一个
authors.stream()
.findFirst()
reduce:归并计算(缩紧操作)
authors.stream()
.map(author -> author.getAge())
//指定初始值和计算操作
.reduce(0, (res, ele) ->{
return res + ele;
})
authors.stream()
.map(author -> author.getAge())
//指定初始值和计算操作
.reduce(Integer.MIN_VALUE, (res, ele) ->{
return ele > res ? ele : res;
})
1个参数,不传入初始值,会把遍历的第一个元素作为初始值,然后计算
authors.stream()
.map(author -> author.getAge())
//指定初始值和计算操作
.reduce((res, ele) ->{
return res + ele;
})
注意
- 惰性求值,必须要有终结操作
- 一次性流,只能使用一次
- 不会影响原来集合的数据
optional使用
- 创建optional
Optional<Author> op = Optional.ofNullable(author);
op.ifPresent((author) -> System.out.print(author)) //消费型接口,非空执行
Optional.of() //这个必须传非空的对象
Optional.empty() //返回空的
- 安全消费
op.ifPresent((author) -> System.out.print(author)) //消费型接口,非空执行
- 安全获取值
op.orElseGet(() -> new Author();)// 不存在则,获取默认值
op.orElseThrow(() -> new RuntimeException("null");)// 不存在则,抛出一个自定义异常
- 过滤数据
op.filter(author -> author.getAge > 18) // 返回Optional对象,过滤掉不符合的数据
- 判断
isPresent(author) ,没啥用和 null != author 一个样子
- 数据转换
op.map((author) -> {
return author.getBooks();
})
函数式接口
建议加上@FunctionalInterface 注解进行标记,但是无论是否加上注解,只要接口中只有一个抽象方法,那就是函数式接口
常用函数式接口
-
Consumer 消费接口
传入一个参数,进行消费,无返回值
-
Function 计算转换接口
传入一个参数进行计算或者转换,然后返回结果
-
Predicate 判断接口
传入一个参数,判断,返回true or false
-
Supplier 生产形接口
-
BiConsumer,BiFunction,BiPredicate 等接口,提供两个参数
方法引用
什么情况下可以使用方法引用?如果只调用了一种方法,就可以
基本格式
类名或者对象名::方法名
类的静态方法
调用的是类的静态方法,并且参数按照顺序传入,就可以使用。
authors.stream()
.map(String::valueOf)
对象的实例方法
调用的是对象的实例方法,并且参数按照顺序传入,就可以使用。
StringBuilder sb = new StringBuilder();
authors.stream()
.map(sb::append)
引用类的实例方法
调用的是引用类的成员方法,调用了第一个参数的成员方法,并且剩余的参数按照顺序传入,就可以使用。其实这个和类的静态方法调用差不多,就是第一个参数的成员方法,也可以这么写。
StringBuilder sb = new StringBuilder();
authors.stream()
.map(类名::方法名)
构造器引用
类名::new ,调用的是构造方法
基本数据类型优化
注意基本数据类型和引用类型的自动拆箱装箱的消耗
例如mapToInt,mapToLong,mapToDouble,flatmapToInt,flatmapToLong,flatmapToDouble
authors.stream()
.mapToInt(author -> author.getAge()) //直接转换成基本数据类型,避免拆箱装箱损耗
.map(age -> age + 10)
并行流
stream.parallel() //转化成为并行流
authors.paralleStream() // 直接获得并行流
stream.peek() //调试方法,中间操作,可以虚假消费,来进行输出调试,不会真正消费数据

浙公网安备 33010602011771号