零、 概述

第一部分:1~3章 主要讲了行为参数化和Lambda表达式

第二部分:4~7章 主要讲了流的应用,包括流与集合差异,流的操作,收集器,注的并行执行

第三部分:8~12章 主要讲了怎样用Java8引入的特性改善老代码,Optional类和CompleteFuture及新的日期和时间API

第四部分:13~16章 主要讲了函数式编程

本文主要是对第一部分的笔记。

一、行为参数化

1.1 行为参数化定义

行为参数化就是拿出一个代码块,把它准备好却不去执行它。

1.2 举例:需求

有个果农,有如下需求:

  1. 从仓库中找到红色苹果
  2. 找出所有重量超过150g的

扩展一下:

  1. 可能以后还需要查找绿色苹果的功能
  2. 可能还需要找重量超过200g的

1.3 举例:方案1

传统实现方案

  1. // 筛选绿色苹果
  2. public static List<Apple> filterGreenApples(List<Apple> inventory) {
  3. List<Apple> result = new ArrayList<>();
  4. for (Apple apple : inventory) {
  5. if ("green".equals(apple.getColor())) {
  6. result.add(apple);
  7. }
  8. }
  9. return result;
  10. }
  11. // 可筛选任意颜色苹果,把颜色作为参数
  12. public static List<Apple> filterGreenApplesByColor(List<Apple> inventory, String color) {
  13. List<Apple> result = new ArrayList<>();
  14. for (Apple apple : inventory) {
  15. if (apple.getColor().equals(apple.getColor())) {
  16. result.add(apple);
  17. }
  18. }
  19. return result;
  20. }
  21. // 筛选不同重量的苹果
  22. public static List<Apple> filterGreenApplesByWeight(List<Apple> inventory, int weight) {
  23. List<Apple> result = new ArrayList<>();
  24. for (Apple apple : inventory) {
  25. if (apple.getWeight() > weight) {
  26. result.add(apple);
  27. }
  28. }
  29. return result;
  30. }
  31. // 写一个方法同时支持筛选颜色和重量
  32. public static List<Apple> filterGreenApples(List<Apple> inventory, String color, int weight
  33. , boolean filterColorFlag) {
  34. List<Apple> result = new ArrayList<>();
  35. for (Apple apple : inventory) {
  36. if ((filterColorFlag && apple.getColor().equals(color))
  37. || (!filterColorFlag && apple.getWeight() > weight)) {
  38. result.add(apple);
  39. }
  40. }
  41. return result;
  42. }

1.4 举例:方案2

使用对象传递行为参数

  1. interface ApplePredicate {
  2. // 一个返回boolea值的函数,把它称为谓词
  3. boolean test(Apple apple);
  4. }
  5. // 筛选绿色
  6. public class AppleGreenColorPredicate implements ApplePredicate {
  7. @Override
  8. public boolean test(Apple apple) {
  9. return "green".equals(apple.getColor());
  10. }
  11. }
  12. // 重量大于150
  13. class AppleHeavyWeightPredicate implements ApplePredicate {
  14. @Override
  15. public boolean test(Apple apple) {
  16. return apple.getWeight() > 150;
  17. }
  18. }
  19. // 红色且重量大于150
  20. class AppleRedAndHeavyPredicate implements ApplePredicate {
  21. @Override
  22. public boolean test(Apple apple) {
  23. return "red".equals(apple.getColor()) && apple.getWeight() > 150;
  24. }
  25. }
  26. // 实现
  27. public static List<Apple> filterApples(List<Apple> inventory, ApplePredicate p) {
  28. List<Apple> result = new ArrayList<>();
  29. for (Apple apple : inventory) {
  30. if (p.test(apple)) {
  31. result.add(apple);
  32. }
  33. }
  34. return result;
  35. }
  36. public void test() {
  37. List<Apple> inventory = new ArrayList<>();
  38. // 筛选绿色
  39. filterApples(inventory, new AppleGreenColorPredicate());
  40. // 重量大于150
  41. filterApples(inventory, new AppleHeavyWeightPredicate());
  42. // 红色且重量大于150
  43. filterApples(inventory, new AppleRedAndHeavyPredicate());
  44. }

1.5 举例:方案3

使用匿名类传递行为参数

  1. // 对选择标准建模
  2. interface ApplePredicate {
  3. // 一个返回boolea值的函数,把它称为谓词
  4. boolean test(Apple apple);
  5. }
  6. // 实现
  7. public static List<Apple> filterApples(List<Apple> inventory, ApplePredicate p) {
  8. List<Apple> result = new ArrayList<>();
  9. for (Apple apple : inventory) {
  10. if (p.test(apple)) {
  11. result.add(apple);
  12. }
  13. }
  14. return result;
  15. }
  16. public static void main(String[] args) {
  17. List<Apple> inventory = new ArrayList<>();
  18. // 筛选绿色
  19. filterApples(inventory, new ApplePredicate() {
  20. @Override
  21. public boolean test (Apple apple){
  22. return "green".equals(apple.getColor());
  23. }
  24. });
  25. // 重量大于150
  26. filterApples(inventory, new ApplePredicate() {
  27. @Override
  28. public boolean test (Apple apple){
  29. return apple.getWeight() > 150;
  30. }
  31. });
  32. // 红色且重量大于150
  33. filterApples(inventory, new ApplePredicate() {
  34. @Override
  35. public boolean test (Apple apple){
  36. return "red".equals(apple.getColor()) && apple.getWeight() > 150;
  37. }
  38. });
  39. }

1.6 举例:方案4

使用Lambda表达式传递行为参数

  1. interface ApplePredicate {
  2. boolean test(Apple apple);
  3. }
  4. public static List<Apple> filterApples(List<Apple> inventory, ApplePredicate p) {
  5. List<Apple> result = new ArrayList<>();
  6. for (Apple apple : inventory) {
  7. if (p.test(apple)) {
  8. result.add(apple);
  9. }
  10. }
  11. return result;
  12. }
  13. public static void main(String[] args) {
  14. List<Apple> inventory = new ArrayList<>();
  15. // 筛选绿色
  16. filterApples(inventory
  17. , (Apple apple) -> "green".equals(apple.getColor()));
  18. // 重量大于150
  19. filterApples(inventory
  20. , (Apple apple) -> apple.getWeight() > 150);
  21. // 红色且重量大于150
  22. filterApples(inventory
  23. , (Apple apple) -> "red".equals(apple.getColor()) && apple.getWeight() > 150);
  24. }

在这里小结一下:

1.7 举例:方案5

在方案4的基础上 将List类型抽象化

  1. // 定义一个函数式接口
  2. interface Predicate<T> {
  3. boolean test(T t);
  4. }
  5. // 定义一个调用函数式接口的方法
  6. public static <T> List<T> filter(List<T> list, Predicate<T> p) {
  7. List<T> result = new ArrayList<>();
  8. for (T e : list) {
  9. if (p.test(e)) {
  10. result.add(e);
  11. }
  12. }
  13. return result;
  14. }
  15. // 使用
  16. public static void main(String[] args) {
  17. List<Apple> inventory = FakeDb.getApples();
  18. List<Apple> redList = Filtering.filter(inventory
  19. , (Apple apple) -> "red".equals(apple.getColor()));
  20. List<String> nonEmptyList = filter(Arrays.asList("1", "", "2")
  21. , (String s) -> !s.isEmpty());
  22. }

二、Lambda表达式

2.1 Lambda表达式定义

简洁地表示可传递的匿名函数的一种方法。

  • 匿名 {:&.fadeIn}
  • 函数
  • 传递
  • 简洁

2.2 Lambda表达式长什么样子?

下面是5个有效的Lambda表达式

  1. // 1 参数是String s,返回值是int
  2. (String s) -> s.length()
  3. // 2 参数是Apple a,返回值是boolean
  4. (Apple a) -> a.getWeight() > 150
  5. // 3 参数是int x,int y 没有返回值 {}内放语句,怎样区分语句与表达式
  6. (int x, int y) -> {
  7. System.out.println("Result:");
  8. System.out.println(x + y);
  9. }
  10. // 4 无参数,返回int
  11. () -> 42
  12. // 5 参数是两个Apple类型的变量,返回值是boolean
  13. (Apple a1, Apple a2) -> a1.getWeight().compareTo(a2.getWeight())

2.3 函数式接口

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

函数式接口的抽象方法的签名基本上就是Lambda表达式的签名,这种抽象方法叫做函数描述符

一个注解:@FunctionalInterface ,不是必须的,用于表示该接口会设计成一个函数式接口

2.4 Lambda的使用

Predicate 过滤掉列表中的空串

  1. // 定义一个函数式接口
  2. interface Predicate<T> {
  3. boolean test(T t);
  4. }
  5. // 定义一个调用函数式接口的方法
  6. public static <T> List<T> filter(List<T> list, Predicate<T> p) {
  7. List<T> result = new ArrayList<>();
  8. for (T e : list) {
  9. if (p.test(e)) {
  10. result.add(e);
  11. }
  12. }
  13. return result;
  14. }
  15. // 使用
  16. public static void main(String[] args) {
  17. List<String> nonEmptyList = filter(Arrays.asList("1", "", "2")
  18. , (String s) -> !s.isEmpty());
  19. }

Consumer 计算列表中的每个元素的平方并输出

  1. @FunctionalInterface
  2. public interface Consumer<T> {
  3. void accept(T t);
  4. }
  5. public static <T> void forEach(List<T> list, Consumer<T> c) {
  6. for (T i : list) {
  7. c.accept(i);
  8. }
  9. }
  10. public static void main(String[] args) {
  11. forEach(Arrays.asList(1, 2, 3, 4), (Integer i) -> System.out.println(i * i));
  12. }

Function** 返回列表中每个元素的长度

  1. @FunctionalInterface
  2. public interface Function<T, R> {
  3. R apply(T t);
  4. }
  5. public static <T, R> List<R> map(List<T> list, Function<T, R> f) {
  6. List<R> result = new ArrayList<>();
  7. for (T s : list) {
  8. result.add(f.apply(s));
  9. }
  10. return result;
  11. }
  12. public static void main(String[] args) {
  13. List<Integer> result = map(Arrays.asList("1", "22", "333")
  14. , (String s) -> s.length());
  15. }

2.5 类型推断

  1. List<Apple> l = new ArrayList<Apple>();
  2. List<Apple> l = new ArrayList<>();
  3. // Java编译器根据Lambda出现的上下文来推断Lambda表达式参数的类型
  4. Predicate<Apple> p = (Apple a) -> 'red'.equals(a.getColor())
  5. Predicate<Apple> p = a -> 'red'.equals(a.getColor())

2.6 方法引用

主要为了简化代码

方法引用,3种

  • 指向静态方法的方法引用 String.parseInt()
  • 指向实例方法的方法引用 str.length()
  • 指向外部对象实例方法的方法引用 globalVar.instanceMethod()
  1. List<String> strList = Arrays.asList("a", "b", "A", "B");
  2. strList.sort((s1, s2) -> s1.compareToIgnoreCase(s2));
  3. strList.sort(String::compareToIgnoreCase); // 等效的方法引用

构造函数引用

  1. Supplier<Apple> c1 = Apple::new; // 指向Apply()构造函数
  2. Apple a1 = c1.get();
  3. Function<Integer, Apple> c2 = Apple::new; // 指向Apply(int weight)构造函数
  4. Apple a2 = c2.apply(110);
  5. BigFunction<String, Integer, Apple> c3 = Apple::new;
  6. // 指向Apply(String color, Integer weight)
  7. Apple c3 = c3.apply("green", 110);

2.7 Lambda实战

根据Apple的重量来排序

  1. // 行为参数化,下面是通过不同方式传递这个行为的
  2. // 1.使用对象
  3. public class AppleComparator implements Comparator<Apple> {
  4. public int compare(Apple a1, Apple a2) {
  5. return a1.getWeight().compareTo(a2.getWeight());
  6. }
  7. }
  8. inventory.sort(new AppleComparator());
  9. // 2.使用匿名类
  10. inventory.sort(new Comparator<Apple>(){
  11. public int compare(Apple a1, Apple a2) {
  12. return a1.getWeight().compareTo(a2.getWeight());
  13. }
  14. });
  15. // 3.使用Lambda表达式
  16. inventory.sort((Apple a1, Apple a2) -> a1.getWeight().compareTo(a2.getWeight()));
  17. // 因为类型推断,可以简化成
  18. inventory.sort((a1, a2) -> a1.getWeight().compareTo(a2.getWeight()));
  19. // 因为有个java.util.Comparator.comparing静态方法,还可以简化成
  20. import static java.util.Comparator.comparing;
  21. inventory.sort(comparing((a) -> a.getWeight()));
  22. // 4.使用方法引用
  23. inventory.sort(comparing(comparing(Apple::getWeight)));

2.8 复合Lambda表达式

比较器复合

  1. // 逆序,苹果按重量递减排序
  2. inventory.sort(comparing(Apple::getWeight).reversed());
  3. // 比较器链,先按重量递减排序再按国家排序
  4. inverntory.sort(comparing(Apple::getWeight).reversed()
  5. .thenComparing(Apple::getCountry));

谓词复合

  1. // negate,and,or
  2. // 筛选不是红苹果
  3. Predicate<Apple> notRedApple = redApple.negate();
  4. // 筛选红苹果且重量大于150 或 绿苹果
  5. redApple.and(a -> a.getWeight() > 150).or(a -> "green".equals(a.getColor()));
  6. // a.or(b).and(c) <==> (a || b) && c

函数复合

  1. // andThen,compose
  2. Function<Integer, Integer> f = x -> x + 1;
  3. Function<Integer, Integer> g = x -> x * 2;
  4. // g(f(x))
  5. Function<Integer, Integer> h = f.andThen(g);
  6. int result = h.apply(1);
  7. // f(g(x))
  8. Function<Integer, Integer> h = f.compose(g);
  9. int result = h.apply(1);

三、代码

https://gitee.com/yysue/tutorials-java/tree/master/java-8

行为参数化与lambda表达式 - 读《Java 8实战》的更多相关文章

  1. Java 终于有 Lambda 表达式啦~Java 8 语言变化——Lambda 表达式和接口类更改【转载】

    原文地址 en cn 下载 Demo Java™ 8 包含一些重要的新的语言功能,为您提供了构建程序的更简单方式.Lambda 表达式 为内联代码块定义一种新语法,其灵活性与匿名内部类一样,但样板文件 ...

  2. Lambda 表达式 in java 8

    Lambda 表达式 in Java 8 Lambda表达式是java 8 新增的特性 Lambda表达式主要作用:支持将代码块作为方法参数,允许使用更简洁的代码创建函数式接口的实例,是匿名内部类的一 ...

  3. Lambda 表达式,Java中应用Lambda 表达式

    一.Lambda 表达式 简单来说,编程中提到的 lambda 表达式,通常是在需要一个函数,但是又不想费神去命名一个函数的场合下使用,也就是指匿名函数. 链接:知乎 先举一个普通的 Python 例 ...

  4. 行为参数化和Lambda表达式

    行为参数化是指拿出一个代码块把他准备好却不执行它.这个代码块以后可以被程序的其他部分调用,意味着你可以推迟这块代码的执行.方法接受多种行为作为参数,并在内部使用来完成不同的行为.行为参数话的好处在于可 ...

  5. Lambda表达式和Java集合框架

    本文github地址 前言 我们先从最熟悉的Java集合框架(Java Collections Framework, JCF)开始说起. 为引入Lambda表达式,Java8新增了java.util. ...

  6. Java 8 (2) 使用Lambda表达式

    什么是Lambda? 可以把Lambda表达式理解为 简洁的表示可传递的匿名函数的一种方式:它没有名称,但它有参数列表.函数主体.返回类型,可能还有一个可以抛出的异常列表. 使用Lambda可以让你更 ...

  7. Java 8新特性(一):Lambda表达式

    2014年3月发布的Java 8,有可能是Java版本更新中变化最大的一次.新的Java 8为开发者带来了许多重量级的新特性,包括Lambda表达式,流式数据处理,新的Optional类,新的日期和时 ...

  8. Java 8特性探究(1):通往lambda之路与 lambda表达式10个示例

    本文由 ImportNew 函数式接口 函数式接口(functional interface 也叫功能性接口,其实是同一个东西).简单来说,函数式接口是只包含一个方法的接口.比如Java标准库中的ja ...

  9. 深入浅出 Java 8 Lambda 表达式

    摘要:此篇文章主要介绍 Java8 Lambda 表达式产生的背景和用法,以及 Lambda 表达式与匿名类的不同等.本文系 OneAPM 工程师编译整理. Java 是一流的面向对象语言,除了部分简 ...

随机推荐

  1. js中一个函数调用另一个函数变量;判断鼠标按住/手指左右滑动

    <script> function myFunction() { var x1=event.clientX;//只需要将被调用的变量前的var删除即可在下个函数调用: document.g ...

  2. 在一个元素上:hover,改变另一个元素的css属性

    如果二者是父子关系,可以写成这种: .face:hover .eye-bottom { margin-top: 30px; } 如果是兄弟关系: .face:hover+.ear-wrap { tra ...

  3. 祖先元素transform非none时在Iphone6上引起后代fixed/absolute元素的怪异表现及解决方案

    如题,祖先元素transform非none时,记录一下Iphone6中引起后代元素fixed参考视图怪异表现和解决方案. 层叠关系及参考视图 层叠上下文是HTML元素的三维概念,这些HTML元素在一条 ...

  4. fetch,终于认识你

    fetch和XMLHttpRequest 如果看网上的fetch教程,会首先对比XMLHttpRequest和fetch的优劣,然后引出一堆看了很快会忘记的内容(本人记性不好).因此,我写一篇关于fe ...

  5. 活字格发布新版本,插件公开,引领Web开发新潮流

    日前,活字格Web 应用生成平台发布V4.0版本,首次公开插件机制,强大的扩展性和系统集成能力,引起业内瞩目. 活字格是由西安葡萄城自主研发的 Web 应用生成平台,提供易用的类Excel可视化设计器 ...

  6. 判断链表是否有环(Java实现)

    判断给定的链表中是否有环.如果有环则返回true,否则返回false. 解题思路:设置两个指针,slow和fast,fast每次走两步,slow每次走一步,如果有环的话fast一定会追上slow,判断 ...

  7. Java JDK 动态代理实现和代码分析

    JDK 动态代理 内容 一.动态代理解析 1. 代理模式 2. 为什么要使用动态代理 3. JDK 动态代理简单结构图 4. JDK 动态代理实现步骤 5. JDK 动态代理 API 5.1 java ...

  8. python关于变量介绍

    python变量 一.变量分为两种解释 1.随时可以变化的量 称之为变量 (变化多端嘛) 2.不会被变化的量 称之为常量 (常常不动嘛) #我们学习的python中没有真正定义的常量 #只有在绑定一个 ...

  9. 生成swap分区之利用磁盘分区

    生成swap 分区方式很多,有利用磁盘分区来生成swap,这种效率比较高,他并不是文件系统, 另外我们还可以拿出磁盘一些空间,做成swap分区还有通过lvm逻辑卷的方式创建swap分区(这种分区就可以 ...

  10. python向上取整以50为界

    import math def getNum(limit_num,num): if num%limit_num==0: print(num) else: num=math.ceil(num/limit ...