第一章 为什么要关心Java 8

  • 语言面临“要么改变,要么衰亡”的压力,工程师面临“要么持续学习,要么淘汰”的压力
  • 现有的Java编程实践并不能很好地利用多核处理器(问:Java 8是如何更好的利用多核处理的?)
  • Java8 新增的Lambda、Sream、Optional等新概念和功能,能够方便我们编写既简洁又高效的程序

    第二章 通过行为参数化传递代码

  • 行为(方法/代码)参数化:就是一个方法接受多个不同的行为作为参数,并在内部使用它们,完成不同行为的能力,可让代码更好的适应不断变化的要求。

优化策略模式

  1. public interface Strategy {
  2. int doOperation(int num1, int num2);
  3. }
  4. public class OperationAdd implements Strategy{
  5. @Override
  6. public int doOperation(int num1, int num2) {
  7. return num1 + num2;
  8. }
  9. }
  10. public class OperationSubstract implements Strategy{
  11. @Override
  12. public int doOperation(int num1, int num2) {
  13. return num1 - num2;
  14. }
  15. }
  16. public class OperationMultiply implements Strategy{
  17. @Override
  18. public int doOperation(int num1, int num2) {
  19. return num1 * num2;
  20. }
  21. }
  22. public class Context {
  23. private Strategy strategy;
  24. public Context(Strategy strategy){
  25. this.strategy = strategy;
  26. }
  27. public int executeStrategy(int num1, int num2){
  28. return strategy.doOperation(num1, num2);
  29. }
  30. }
  31. // 传统策略方式实现,弊端,每个策略对应一个策略类
  32. @Test
  33. public void traditionalStrategyPatternTest() {
  34. Context context = new Context(new OperationAdd());
  35. System.out.println("10 + 5 = " + context.executeStrategy(10, 5));
  36. context = new Context(new OperationSubstract());
  37. System.out.println("10 - 5 = " + context.executeStrategy(10, 5));
  38. context = new Context(new OperationMultiply());
  39. System.out.println("10 * 5 = " + context.executeStrategy(10, 5));
  40. }
  41. // 使用行为参数化的方式进行优化,只需依赖两个即可实现,具体的策略转化为行为参数,避免策略过多引起的策略类爆炸问题
  42. @Test
  43. public void behavioralParamsStrategyPatternTest() {
  44. Context context = new Context(((num1, num2) -> num1 + num2));
  45. System.out.println("10 + 5 = " + context.executeStrategy(10, 5));
  46. context = new Context(((num1, num2) -> num1 - num2));
  47. System.out.println("10 - 5 = " + context.executeStrategy(10, 5));
  48. context = new Context(((num1, num2) -> num1 * num2));
  49. System.out.println("10 * 5 = " + context.executeStrategy(10, 5));
  50. }
  51. // 匿名内部类同样页可实现类似上述的需求,但相对于行为参数化来说更加啰嗦,不够简洁

第三章 Lambda表达式

  • Lambda:可理解为简洁的表示可传递的匿名函数的一种方式,它没有名称,但有参数列表、函数主题、返回类型、还可包含一个可抛出的异常列表
  • Lambda构成:Lambda由参数列表、尖头(->)、主体组成
  • 基本语法
  1. (parameters) -> expression
  2. // 或
  3. (parameters) -> {expression;}

示例:

  1. (Integer number1,Integer number2) -> number1+number2
  • 使用方式:可以在任何函数式接口上使用lambda表达式
  • 函数式接口定义:只定义了一个抽象方法的接口
  • 环绕执行模式:反向AOP,AOP是在业务逻辑之外增加切点切面,执行诸如日志记录,事务控制等操作,而环绕执行则是在“切点”,“切面”定义好的情况下,执行不同的业务逻辑。

示意图:
image.png
如业务需求为读取某个资源之前,需要初始化相关的资源,读取之后,需要关闭对应的资源
伪代码如下:

  1. interface Reader{
  2. void reader();
  3. }
  4. public void read(Reader reader){
  5. // 读取之前的准备操作
  6. preSomething();
  7. // 执行读取
  8. reader();
  9. closeSomething();
  10. }
  11. public static void main(String[] args){
  12. read(System.out.println("读取xxxx.file"));
  13. read(System.out.println("读取xxxx.sql"));
  14. read(System.out.println("读取xxxx.hd"));
  15. }
  • 类型检查:上下文
  • 类型推断:上下文
  • 使用局部变量:局部变量必须显示的声明为final,如在表达式中使用了局部变量,并对局部变量进行了二次赋值,则会编译报错(原因:实例变量存储在堆中,局部变量在栈中)
  • 方法引用:可以重复使用现有的方法定义,并像lambda一样传递,可看作调用特定方法的Lambda的一种快捷调用方式,相当于Lambda的语法糖

示例

  1. List<Integer> integers = Arrays.asList(23, 123, 4, 5, 6);
  2. // lambda 方式
  3. integers.forEach(a->System.out.println(a));
  4. // 方法引用
  5. integers.forEach(System.out::println);
  • 方法引用的分类:

    • 类名指向静态方法的引用
    • 类名指向任意类型实例方法的方法引用
    • 指向现有对象的实例方法的方法引用
  • 总结:

函数式编程相对于指令式编程,函数式编程只需要指出希望的结果-“做什么”,而不用操心执行的步骤-“如何做”