历时一个多月,断断续续看完了这本书。
Java8是一个变化很大的版本
值得用心学习新特性
特别是:
Stream:处理集合很方便,就像写SQL;
Optional:防止NEP利器;
目前这两个我用的比较多
身边的同事也慢慢接受了
因为实在是方便。
以下是笔记
——————
新特性:lambda(匿名函数)、流、默认方法
Java1.8以前并不支持并行处理数据。
Java8对程序猿的主要好处是在于它提供了更多的编程工具和概念,能以更快,更重要的是以更简洁、更易于维护的方式解决新的或现有的编程问题。
stream以流水线似的方式对数据并行处理。
用行为化参数把代码传递给方法,stream api就是构建在通过传递代码使操作行为实现参数化的思想上的。
没有共享的可变数据,将方法和函数即代码传递给其他方法的能力,是我们平常所说的函数式编程范式的基石。
Java8的方法引用::语法(把方法作为值值)传给其他方法。
stream有内部迭代器。
Collection主要是为了存储和访问数据,stream主要用于描述对数据的计算。这里的关键点在于,stream允许并提倡并行处理一个stream中的元素。
stream并行处理,可以把任务分给多个CPU,然后各自处理,还有某个CPU对结果合并起来。
list.stream顺序处理
list.parallelStream并行处理
你如何改变已发布的接口而不破坏已有的实现呢?——Java8做到了,如今接口可以包含实现类没有提供实现的方法签名了。
行为化参数就是可以帮助你处理频繁变更的需求的一种软件开发模式。行为参数化:让方法接受多种行为作为参数,并在内部使用,来完成不同的行为。
匿名内部类,随建随用
第2章小结:
1. 行为参数化,就是一个方法接受多个不同的行为作为参数,并在内部使用他们,完成不同行为的能力。
2. 行为参数化可让代码更好地适应不断变化的要求,减轻未来的工作量
3. 传递代码,就是将新行为作为参数传递给方法。但在Java8之前,这实现起来很啰嗦。为接口声明许多用一次的实体类而造成的啰嗦代码,在Java8之前可以使用匿名类来减少。
4. Java API包含很多可以用不同行为参数化的方法,包括排序、线程、GUI处理。
第3章 lambda表达式
本章的行文思想就是教你一步步地写出更简洁、更灵活的代码。
lambda基本的特征:匿名、函数、传递、简洁。
lambda基本语法:
(parameters) -> expression
或者
(parameters) -> { statements; }
函数式接口就是只定义定义一个抽象方法的接口。
哪怕有很多默认方法,只要接口定义了一个抽象方法,它就仍然是一个函数式接口。
lambda的类型是从使用lambda的上下文推断出来的。上下文中lambda表达式需要的类型称为目标类型。
捕获lambda:能获取final或者事实上是final的实例变量和静态变量。(上下文中不允许修改变量)
闭包就是一个函数的实例,且他可以无限制得访问那个函数的非本地变量。
因为filter、sorted、map和collect等操作是与具体线程模型无关的
高层次构件,所以它们的内部实现可以是单线程的,也可能透明地充分
利用你的多核架构!
Java8 stream api写出的代码特点:
声明性——更简洁、更易读
可复合——更灵活
可并行——性能更好
流:从支持数据处理操作的源生
成的元素序列,流的目的在于表达计算。
集合讲的是数据,流讲的是计算。
链中的方法调用都在排队等待,直到调用collect。
filter——接受Lambda,从流中排除某些元素。
map——接受一个Lambda,将元素转换成其他形式或提取信息。
limit——截断流,使其元素不超过给定数量。
collect——将流转换为其他形式。
stream api自带很多方法,他可以自动优化流的执行步骤。
集合与流之间的概念差异就是在于何时开始计算。
内部迭代时,项目可以透明地并行处理,或者用更优化的顺序进行处理。
中间操作:会返回一个流,不做任何事
终端操作:一次性处理完成。
归约操作,将流归约成一个值。
IntSummaryStatistics会返回count、sum、min、average、max。
reduce方法旨在把两个值结合起来生成一个新的值,它是一个不可变归约。与此相反,collect方法的设计就是要改变容器,从而累积要输出的结果。
groupingBy(f)实际上是
groupingBy(f,toList())的简写
paralle()将流转换为并行流
选择合适的数据结构往往比并行化算法更重要。
使用正确的数据结构然后使其并行工作能保持最佳的性能。
共享可变状态会影响并行流以及并行计算。
分支/合并框架的目的是以递归方式将可以并行的任务拆分成更小的任务,然后将每个子任务的结果合并起来生成整体结果。
可以使用显式的类型转换来避免lambda模棱两可的情况。
建议将所有使用迭代器处理集合的代码都转换成stream API,因为stream API更清晰的表达数据处理管道的意图。
采用函数接口,重构模式:有条件的延迟执行 和 环绕执行。
策略模式和模板方法,这些在使用lambda表达式重写后会更简洁。
环绕执行:业务代码千差万别,但是他们拥有同样的准备和清理阶段,这时,你完全可以将这段代码用lambda实现。
我们会展示lambda表达式是如何另辟蹊径解决设计模式原来试图解决的问题。
模板方法:如果你需要采用某个算法框架,同时也希望有一定的灵活度,能对他的某些部分进行修改,那么采用模板方法比较通用。
责任链模式:链式处理,andThen();
将复杂的lambda表达式分到不同的方法中
引入默认方法的目的:类可以自动地继承接口的一个默认实现。
为接口添加一个方法是二进制兼容。
引入变化后,现有的程序依然能成功编译通过,就是源代码级兼容。
你永远也不该忘记语音的首要功能就是沟通,即使对程序设计语言也没有什么不同。
optional.orElseThrow() 不为空取出数据,为空抛出异常,并且可以自定义异常。
flatMap:XX.flatMap() ,与map类似,只是XX为空值不会执行逻辑。
optional.filter()
每次你希望安全地对潜在为null的对象进行转换,并将其替换为Optional对象时,都可以考虑这个方法:
Optional<Object> value =
Optional.ofNullable(map.get("key"))
使用Optional包装各种工具类
比如String2Integer:
try{
return Optional.of(Integer.parseInt(s);
}catch (NumberFormatException e){
return Optional.empty();
}
守护进程:程序退出时,会被回收。
使用API的建议:
1)如果是计算密集型的操作,并没有io,那么推荐stream
2)如果涉及等待io,那么使用completeableFuture灵活性更好
Java并发编程实战:线程池的大小与处理器的利用率之比可以使用下面的公式计算:
“函数式”准则:这种函数或者方法都只能修改本地变量,而且不应该抛出任何异常。
基于尾递的递归,性能更好。不需要在不同的栈帧上保存每次递归计算的中间值,提高效率。
应该尽量使用stream进行迭代操作,从而避免变化带来的影响。
减少共享可变的数据结构能帮助你降低维护和调试程序的代价。
能够像普通变量一样使用的函数称为一等函数。
高阶函数:
1)接受至少一个函数作为参数
2)返回的结果是一个函数
科里化:它是一种可以帮助你模块化函数,提高代码重用性的技术。
科里化:他表示一种将一个带有n元组参数的函数转换成n个一元函数链的方法。
当你向stream发起一个终端操作时,才会实际地进行计算。
一旦并发和共享可变状态的对象揉到一起,他们引起的复杂度远超我们的想象,而函数式编程能从根本上解决问题。
抽空看看scala的著名API
Function<String,Boolean> isBig2=
(String s) -> s.length() > 2;
isBig2.apply("hisen");
Java8新特性是自Java创建以来最大的一次演变。
checker框架
Adder () Accumulate()频繁更新,很少读的场景
ConcurrentHashmap 当桶过于臃肿时,会转换为排序树,新增了好些方法操作自己。
Files.lines list walk
String.jion()
网友评论