• 《Java8实战》读书笔记&常用lambda表达式


    有用的笔记:

    1.如果需要传递函数到方法内,简单的可以使用function函数(只支持一个入参),复杂的可以通过@FunctionalInterface自定义函数式接口来实现。

    个人感悟:

    1.lambda表达式,补充了JAVA在面向对象之外,面向过程的一面。在写面向过程代码的时候更方面了,甚至可以利用代码来做类似数学公式的运算(P64)

    2.流,对集合的操作,就像用SQL对数据表的操作那样,屏蔽了实现,节约了开发时间(P68)

    3.流可以处理集合,但是这2者是完全不同的2个概念。集合是急切创建的,流则是按需生成(就像碟片播放和在线播放)(P74)

    4.函数式编程相对于指令式编程的一个主要优势:你只需指出希望的结果——“做什么”,而不用操心执行的步骤——“如何做”。(P112)

    5.函数式编程(特别是Java 8的 Collections 框架中加入的基于函数式风格原 理设计的新API)通常提供了多种方法来执行同一个操作。(P119)

    ---------------2019-4-25笔记更新--------------

    1.option要结合lambda表达式使用才美味,不要单独使用

    2.lambda表达式:匿名函数的一种简洁的表达形式

    3.函数式接口:只定义一个抽象方法的接口(打上@FunctionalInterface标签)

    PS.可以在函数式接口上使用lambda表达式,使代码的设计模式更优雅

    4.语法糖演进:接口实现类 -> 匿名类 -> lambda表达式 

    5.类型推断:java编译器可以通过上下文推断出lambda表达式的参数类型,因此可以省略 (有时候为了代码易读性,也可以显示的写类型)

    6.方法引用:lambda的语法糖,如(Apple a) -> a.getWeight()可以写成Apple::getWeight

    P53.lambda这一章很精彩。一定要仔细读完!

    ---------------分割线--------------

    一、基础知识

    1.从有点修正主义的角度来看,在Java 8中加入 Streams 可以看作把另外两项扩充加入Java 8 的直接原因:把代码传递给方法的简洁方式(方法引用、Lambda)和接口中的默认方法。

    2.Java 8里面将代码传递给方法的功能(同时也能够返回代码并将其包含在数据结构中)还让 我们能够使用一整套新技巧,通常称为函数式编程。

    3.Java 8提供了一个新的API(称为“流”,Stream),它支持许多处理数据的并行操作,其思路 和在数据库查询语言中的思路类似——用更高级的方式表达想要的东西,而由“实现”(在这里 是Streams库)来选择最佳低级执行机制。

    4.这两个要点(没有共享的可变数据,将方法和函数即代码传递给其他方法的能力)是我们平常所说的函数式编程范式的基石

    5.如果极端点儿来说,传统的面向对象编程和函数式可能看起来是冲突的。但是我们的理念是获得两种编程范式中最好的东西,这样你就有更大的机会为任务找到理想的工具了

    6.方法引用:让方法作为值 也构成了其他若干Java 8功能(如 Stream )的基础,编写把函数作为一等值来传递的程序。

    7.有了Stream API,你根本用不着操心循环的事情。数据处 理完全是在库内部进行的。我们把这种思想叫作内部迭代

    8.Java中从函数式编程中引入的两个核心思想:将方法和Lambda作为一等值,以及在没有可变共享状态时,函数或方法可以有效、安全地并行执行

    9.匿名函数必须要传一个对象进方法,而Lambda表达式可以只关心方法

    10.Lambda 的基本语法是 (parameters) -> expression 或 (parameters) -> { statements; }(请注意语句的花括号)。注意,表达式(expression )和语句(statements)不能互换。

    11.函数式接口就是只定义一个抽象方法的接口

    12.有了目标类型的概念,同一个Lambda表达式就可以与不同的函数式接口联系起来,只要它们的抽象方法签名能够兼容。

    13.Lambda有点像闭包。可以认为Lambda是对值封闭,而不是对变量封闭(局部变量必须为final)。

    14.当你需要使用方法引用时,目标引用放在分隔符 :: 前,方法的名称放在后面

    二、函数式数据处理

    1.流的简短的定义就是“从支持数据处理操作的源生成的元素序列”

    2.集合讲的是数据,流讲的是计算

    3.流只能消费一次(只能遍历一次)

    4.集合处理数据用外部迭代,而流用内部迭代(另外,for-eache是Iterator的语法糖)

    5.中间操作一般都可以合并起来,在终端操作时一次性全部处理(效率更好,流中的元素是按需计算的)

    6.flatmap 方法让你把一个流中的每个值都换成另一个流,然后把所有的流连接 起来成为一个流。

    ---------------分割线--------------

    常用方法:

    一、谓词

    1.filter():筛选

    2.distinct():去重

    3.limit():截断

    4.skip():跳过

    二、映射

    1.map():映射

    2.flatmap():拍平,汇合

    三、查找和匹配

    1.allMatch 、 anyMatch 、 noneMatch 、 findFirst 和 findAny(这2个区别是并行和效率)

    四、规约

    1.reduce():规约

    五、数值流

    1.IntStream 、 DoubleStream 和 LongStream

    2.mapToInt 、 mapToDouble 和 mapToLong

    3.boxed()(装箱,和上面操作相反)

    4.OptionalInt 、 OptionalDouble 和 OptionalLong

    5.Arrays.stream():从数组创建一个流

    六、收集流

    1.Collectors.toList()

    2.Collectors.summingInt():求和

    3.Collectors.summarizingInt():汇总(同样还有summarizingLong 和 summarizingDouble )

    4.collect(groupingBy(Lambda表达式)):分组

    5.Collectors.collectingAndThen():分组,并返回指定类型(和上面那个方法对应,是上面方法的扩展)

    6.groupingBy():分组

    7.partitioningBy():分区

    8.可以自定义收集类:需要实现3-5个接口

    七、并行流

    八、重构、测试和调试

    九、默认方法

    1.相同函数签名的继承原则:

    (1) 类中的方法优先级最高。类或父类中声明的方法的优先级高于任何声明为默认方法的优先级。
    (2) 如果无法依据第一条进行判断,那么子接口的优先级更高:函数签名相同时,优先选择拥有最具体实现的默认方法的接口,即如果 B 继承了 A ,那么 B 就比 A 更加具体。
    (3) 最后,如果还是无法判断,继承了多个接口的类必须通过显式覆盖和调用期望的方法,显式地选择使用哪一个默认方法的实现。

    十、用optional取代null

    十一、completeFuture

    十二、新的日期和时间API

    十三、函数式的思考

    十四、函数式编程的技巧

    十五、面向对象和函数式编程的混合:Java和 Scala的比较

    十六、结论以及Java的未来

    X、其它

    1.count():计算流的元素个数

    ---------------分割线--------------

    常用示例代码:

    1)获取list对象的内容合并成List:

      List<Long> childModuleIdList = childModuleList.stream().map(StudyModuleDO::getId).collect(Collectors.toList());

    2)List转Map:

      注意:lambda表达式转map时,toMap的第2个参数,value值不能为null,否则会空指针。map本身支持value存null,所以应该是lambda表达式的机制导致的

      Map<Date, List<DailyStatusBO>> dateList = dailyStatusList.stream().collect(Collectors.groupingBy(DailyStatusBO::getDate)); //不去重

      Map<Integer, Student> map = list.stream().collect(Collectors.toMap(Student::getId, student -> student)); //去重

      返回对象本身的语法糖:Function.identity()

    3) list转set

      userIdList.stream().map(userIdAndBbsIdMap::get).collect(Collectors.toSet());

    4)map转list

      map.entrySet().stream().map(e -> new Person(e.getKey(),e.getValue())).collect(Collectors.toList());

    5)筛选

      List<User> collect = list.stream().filter(user -> user.getAge()<30 && "女".equals(user.getSex())).collect(Collectors.toList());

    代码示例:

    1.List<Dish> vegetarianDishes = menu.stream() .filter(Dish::isVegetarian) .collect(toList());

    2.List<String> uniqueCharacters = words.stream() .map(w -> w.split("")) .flatMap(Arrays::stream) .distinct() .collect(Collectors.toList());

    3.int sum = numbers.stream().reduce(0, Integer::sum);

    4.Optional<Integer> sum = numbers.stream().reduce((a, b) -> (a + b));(可能无值,所以用Optional接)

    5.OptionalInt maxCalories = menu.stream() .mapToInt(Dish::getCalories) .max();

    6.IntStream evenNumbers = IntStream.rangeClosed(1, 100) .filter(n -> n % 2 == 0);

    7.Stream<String> stream = Stream.of("Java 8 ", "Lambdas ", "In ", "Action");

    8.int totalCalories = menu.stream().collect(summingInt(Dish::getCalories));

    9.String shortMenu = menu.stream().map(Dish::getName).collect(joining(", "));

    10.Map<Dish.Type, List<Dish>> dishesByType = menu.stream().collect(groupingBy(Dish::getType));

    11.Map<Dish.Type, Set<CaloricLevel>> caloricLevelsByType = menu.stream().collect( groupingBy(Dish::getType, mapping( dish -> { if (dish.getCalories() <= 400) return CaloricLevel.DIET; else if (dish.getCalories() <= 700) return CaloricLevel.NORMAL; else return CaloricLevel.FAT; }, toCollection(HashSet::new) )));(上面那个例子的复杂版)

    ----------------附录---------------

    P100:小练习,可以用来熟悉lambda表达式

    P104:小练习,可以实现提取勾股数

    P107:小练习,生成斐波纳契数列

    P128:小练习 将数字按质数和非质数分区

    有用的东西:

    1.Collectors类的静态工厂方法列表:P128

  • 相关阅读:
    javascript实现根据时间段显示问候语的方法
    视觉会议收藏一
    cv的期刊和会议
    CVPR2016 Paper list
    CVPR 2017 Paper list
    关注的牛人
    cvpr2016论文
    linux命令技巧:scp多文件远程拷贝
    linux命令技巧--df -lh:查看磁盘占用情况
    spark--01编译安装spark1.3.1
  • 原文地址:https://www.cnblogs.com/xujanus/p/7201951.html
Copyright © 2020-2023  润新知