1251-java8+lambda
2020-06-28 11:01:16 0 举报
AI智能生成
lambda, java8, stream
作者其他创作
大纲/内容
为什么用java8
远远不够
juc的包
分支主题
处理大型数据集合
欠缺高效的并发操作
函数式编程
面向对象》对数据进行抽象
函数式编程》对行为进行抽象
核心:
思考问题时
使用不可变值和函数
函数对一个值进行处理
映射为另一个值
模型示例:
Music
Arties
创作音乐的个人或团队
name
member
origin
来自哪里
Track
专辑中的一支曲目
name
Album
专辑
name
tracks
所有曲目的列表
musicians
参与创作专辑的艺术家列表
Lambda表达式
也成为闭包
第一个Lambda
去除样板代码
易读
lambda的类型依赖于上下文环境
是由编译器推断出来
如果参数类型不言而明,则无需显式指定
如
final String [] aa = {"v","a"}
如何辨别Lambda
Runnable noArgs = () -> Sout "";
() = 无参数
直接写方法内存。接口只有1个run方法
Runnable multiStatement = () -> {sout1,sout2}
可以是一句话可以是代码块
ActionListener oneArgs = event -> sout""
1个参数,省略()
BinaryOperator add = (x,y) -> x+y
变量ADD的类型是前面
算2个参数之和
BinaryOperator add = (Long x,Long y) -> x+y
也可以声明参数类型
引用的值而不是变量
既成事实的final值
虽然不是final但是
String name = getUserName;
button.addActionListener(event -> sout"hi + "+name)
只能给变量赋值一次
如果再次赋值,则不能编译通过
函数接口
lambda本身的类型
函数接口是?
一个抽象方法的接口
用作lambda表达式的类型
重要的函数接口
1、Predicate
boolean
判断
唱片发型了吗
分支主题
2、Consumer
void
输出值
3、Function
参数T,返回R
获得artlist对象
分支主题
4、Supplier
供应商
参数无,返回T
工厂方法
5、UnaryOperaor
一无运算
参数T,返回T
逻辑非!
6、BinaryOperator
二进制的
参数T,T,返回T
求两个数的乘积
类型推断
是否写类型视情况而定
泛型里的推断
Set a = new HashSet<>();
方法里的推断
如果方法里有泛型,调用的时候可以省略类型
流
关键!
3.1-从外部迭代
解决套循环的代码不易读
封装了迭代的语法糖
iterator迭代
hashNext
next
分支主题
外部迭代
本质串行化操作
3.1-内部迭代
分支主题
不是返回控制迭代的iterator对象。
返回内部迭代中的接口,Stream
例子3-3
long count = allArtists.stream().filter(artist -> artist.isFrom("china")).count();
分解为1过滤2计数
迭代一次
Stream是用函数式编程方式
在集合类上进行复杂操作的工具
3.2-实现机制
Stream对象不是一个新集合
而是创建新集合的配方
惰性求值方法
只描述,不产生新集合
上述3-3例子
过滤+计数
long count = allArtists.stream().filter(artist -> artist.isFrom("china")).count();
判断返回值:Stream则是惰性求值
及早求值方法
描述,且产生值
例3-4
只过滤,不计数
allArtists.stream().filter(artist -> artist.isFrom("china"));
判断返回值:是其他值则是及早求值
3.3-常用的流操作
map = 值换值
flatMap = 流换值
filter = 过滤
1、collect(toList())
***第五章
由Stream里面的值生成一个列表
及早求值
List collected = Stream.of("a","b","c").collecct(Collectors.toList());
首先由列表生成一个Stream
然后Stream上的操作
然后是collect操作
由stream生成列表
2、map
如果有一个函数可以将一种类型的值,转换成另一种类型,
map操作就可以使用该函数,将一个流中的值转成另一个新的流
分支主题
例子:使用map操作将字符串转换为大写形式
3-3
3、FIlter
遍历数据并检查其中元素
分支主题
例子1,找出以数字开头的字符串
常规做法
for,判断开头
lambda函数
3-11
List beginningWithNumbers = Stream.of("a","1a").filter(value -> isDigit(value.charAt(0))).collect(toList());
4、flatMap
可以用Stream来替换值
分支主题
例子:假设有一个包含多个列表的流,现在希望得到所有数字的序列
LIst together = Stream.of(asList(1,2),asList(3,4)).flatMap(numbers -> numbers.stream()).collect(toList);
5、Max和Min
求最大值最小值
常规方法
for循环,默认最小值,一个个比较,替换最小值
lambda方法
传递Comparator对象
comparing静态方法
比较的属性要有get方法
调用空的maxmin方法
返回Optional对象
代表可能存在
Stream不为空
代表可能不存在
Stream空
get()就是去除Optional对象的值
6、通用模式
Reduce模式
reduce减少
如循环比大小例子
模式
分支主题
给初始值
循环做运算
再给初始值赋值
最后是结果
7、Reduce
求和公式看4.3
从一组值中生成一个值
max,min等都是
累加器
分支主题
求和
int count = Stream.of(1,2,3).reduce(0,(acc,element) -> acc+element);
返回值是acc,是上一轮acc的值和当前元素相加的值的结果
BinaryOperator
求乘积
int count = Stream.of(1,2,3).reduce(1,(result,element)->result*element);
8、整合操作
一个需求可能由多个步骤来做,要整合Stream方法
例如:找出某张Album上所有乐队的国籍。
分解
1、找出album所有的表演者
getMusicians.stream()
2、分标出哪些表演者是乐队
filter(arties -> artist.getType() == 1)
3、找出每个乐队的国籍
map(artist -> artist.getNationality())
4、放入一个集合
collect(toSet());
3.4-重构遗留代码
如例子:选出长度大于一分钟的曲目
分支主题
分支主题
分支主题
第一步修改for循环,使用Stream的forEach方法替换for循环,
依然保留原来循环体中的代码,技巧
调用Stream方法,从专辑列表中生成第一个Stream
3.5-多次调用流操作
不要将所有方法调用连接在一起
可读性差
效率差
及早求值
充斥垃圾变量
难于自动并行化处理
3.6-高阶函数
高阶函数是指
接受另外一个函数作为参数,返回一个函数的函数
3.7-正确使用lambda表达式
避免副作用
输出信息
如-> 后面有sout
给变量赋值
给成员变量赋值等
例外:forEach
是个终结方法
3.8-要点问题
内部迭代,将更多控制权交给了集合类
和Iterator类似,Stream是一种内部迭代方式
lambda和Stream的方法结合起来,可以完成很多常见的集合操作
3.9-见0339
list.stream().reduce(0,(result,temp)->result+temp);
分支主题
类库
在代码中使用lambda
和调用普通接口没区别
案例,日志
基本类型
拆箱
装箱类型转成基本类型
(对象转基本Integer转int)
装箱
基本类型转成装箱类型
Stream类的某些方法对基本类型和装箱类型做了区分
占内存开销差距大,基本类型很小。装箱类型很大
仅对三个特殊处理
1、整形
2、长整型
3、双浮点型
例子:4-4
mapToInt
将流映射成曲目长度
返回IntStream流对象
包含SummaryStatistics方法
能计算各种值
max,min,average,sum
album.getTracks().mapToInt(track -> track.getLength()).summaryStatistics();
System.out.printf("Max: %d, Min: %d, Ave: %f, Sum: %d",
trackLengthStats.getMax(),
trackLengthStats.getMin(),
trackLengthStats.getAverage(),
trackLengthStats.getSum());
4.3-重载解析
分支主题
4.4-@FunctionalInterface
4.5-二进制接口的兼容性
4.6-默认方法
Collection父类中有了Stream的方法
4.7-多重继承
4.8-权衡
4.9-接口的静态方法
4.10-Optional
可选择的,随意的
Optional是为核心类库设计的一个数据类型
不同于null
替换null值
nullPointerException
2个目的
1、Optional对象鼓励检查孔
2、它将一类的API中,可能为空的值,文档化
?
例子
分支主题
高级集合类和收集器
5.1-方法引用
简写
ClassName::methodName
artist -> artist.getName()
Artist::getName
5.2-元素顺序
有序集合如list
生成的流是有序的
无序集合如set
生成的流也是无序
stream().forEachOrdered
5.3-使用收集器
java.util.stream.Collectors
转换成其他集合
默认由框架自动选择集合类型
toCollection,定制具体集合
stream.collect(toCollection(TreeSet::new))
转换成值
找出member最多的artist
artist.collect(maxBy(comparing(artist-> artist.getMembers().stream().count)))
minBy, maxBy
albums.stream().collect(averagingInt(album -> album.getTrackList().size()))
数据分块
partitioningBy
接受一个流,分成两部分
分支主题
将artist中,独唱歌手和乐队分开
Map> map = artists.collect(partitioningBy(artist -> artist.isSolo()))
artists.collect(partitioningBy(Artist::isSolo))
数据分组
groupingBy
更自然的分隔数据操作
使用任意值对数据分组
分支主题
按主唱对专辑分组
Map> map = albums.collect(groupingBy(album->album.getMainMusician()))
字符串
很多时候是为了生成字符串
某一张album的所有artist的名字做成字符串
使用for格式化
StringBuilder builder = new StringBuilder("[")
for(Artist artist: artists){
if(builder.length() > 1){
builder.append(",")
}
String name = artist.getName();
builder.append(name);
}
builder.append("]");toString
使用Stream
artists.stream().map(artist -> artist.getName()).collect(Collectors.joining(",","[","]"))
artists.stream().map(Artist::getName).collect(Collectors.joining(",","[","]"))
组合收集器
组合起来使用
counting()
计数
计算每个艺术家专辑数
先groupingBy分类musician,再收集counting,最后映射map
albums.collect(groupingBy(album->album.getMainMusician(),counting()))
mapping()
允许在收集器的容器上执行类似map的操作,但是需要指明用什么样的类存储结构
使用收集器求每个艺术家的专辑名
Map> map = albums.collect(groupingBy(Album::getMainMusician, mapping(Album::getName, toList())))
重构和定制收集器
对收集器的归一化处理
一些细节
集合里的新方法
computeIfAbsent
值不存在时使用lambda
如缓存
cache.getName
if null GetByDb
artistCache.computeIfAbsent(name,this::readFromDB)
map里遍历的新方法,forEach
数据并行化
6.1-并行和并发
并行,多CPU多任务
十吨货物,10个车拉
并发-单CPU多任务
2堆10吨货物,1个车一会拉A一会拉B
测试、调试和重构
设计和架构的原则
使用lambda表达式编写并发程序
为什么要使用非阻塞式IO
非阻塞式IO,异步IO
0 条评论
下一页