博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
行为参数化与lambda表达式 - 读《Java 8实战》
阅读量:5959 次
发布时间:2019-06-19

本文共 9702 字,大约阅读时间需要 32 分钟。

  hot3.png

零、 概述

第一部分: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

传统实现方案

// 筛选绿色苹果public static List
filterGreenApples(List
inventory) { List
result = new ArrayList<>(); for (Apple apple : inventory) { if ("green".equals(apple.getColor())) { result.add(apple); } } return result;}// 可筛选任意颜色苹果,把颜色作为参数public static List
filterGreenApplesByColor(List
inventory, String color) { List
result = new ArrayList<>(); for (Apple apple : inventory) { if (apple.getColor().equals(apple.getColor())) { result.add(apple); } } return result;}// 筛选不同重量的苹果public static List
filterGreenApplesByWeight(List
inventory, int weight) { List
result = new ArrayList<>(); for (Apple apple : inventory) { if (apple.getWeight() > weight) { result.add(apple); } } return result;}// 写一个方法同时支持筛选颜色和重量public static List
filterGreenApples(List
inventory, String color, int weight , boolean filterColorFlag) { List
result = new ArrayList<>(); for (Apple apple : inventory) { if ((filterColorFlag && apple.getColor().equals(color)) || (!filterColorFlag && apple.getWeight() > weight)) { result.add(apple); } } return result;}

1.4 举例:方案2

使用对象传递行为参数

interface ApplePredicate {    // 一个返回boolea值的函数,把它称为谓词    boolean test(Apple apple);}// 筛选绿色public class AppleGreenColorPredicate implements ApplePredicate {    @Override    public boolean test(Apple apple) {        return "green".equals(apple.getColor());    }}// 重量大于150class AppleHeavyWeightPredicate implements ApplePredicate {    @Override    public boolean test(Apple apple) {        return apple.getWeight() > 150;    }}// 红色且重量大于150class AppleRedAndHeavyPredicate implements ApplePredicate {    @Override    public boolean test(Apple apple) {        return "red".equals(apple.getColor()) && apple.getWeight() > 150;    }}// 实现public static List
filterApples(List
inventory, ApplePredicate p) { List
result = new ArrayList<>(); for (Apple apple : inventory) { if (p.test(apple)) { result.add(apple); } } return result;}public void test() { List
inventory = new ArrayList<>(); // 筛选绿色 filterApples(inventory, new AppleGreenColorPredicate()); // 重量大于150 filterApples(inventory, new AppleHeavyWeightPredicate()); // 红色且重量大于150 filterApples(inventory, new AppleRedAndHeavyPredicate());}

1.5 举例:方案3

使用匿名类传递行为参数

// 对选择标准建模interface ApplePredicate {    // 一个返回boolea值的函数,把它称为谓词    boolean test(Apple apple);}// 实现public static List
filterApples(List
inventory, ApplePredicate p) { List
result = new ArrayList<>(); for (Apple apple : inventory) { if (p.test(apple)) { result.add(apple); } } return result;}public static void main(String[] args) { List
inventory = new ArrayList<>(); // 筛选绿色 filterApples(inventory, new ApplePredicate() { @Override public boolean test (Apple apple){ return "green".equals(apple.getColor()); } }); // 重量大于150 filterApples(inventory, new ApplePredicate() { @Override public boolean test (Apple apple){ return apple.getWeight() > 150; } }); // 红色且重量大于150 filterApples(inventory, new ApplePredicate() { @Override public boolean test (Apple apple){ return "red".equals(apple.getColor()) && apple.getWeight() > 150; } });}

1.6 举例:方案4

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

interface ApplePredicate {    boolean test(Apple apple);}public static List
filterApples(List
inventory, ApplePredicate p) { List
result = new ArrayList<>(); for (Apple apple : inventory) { if (p.test(apple)) { result.add(apple); } } return result;}public static void main(String[] args) { List
inventory = new ArrayList<>(); // 筛选绿色 filterApples(inventory , (Apple apple) -> "green".equals(apple.getColor())); // 重量大于150 filterApples(inventory , (Apple apple) -> apple.getWeight() > 150); // 红色且重量大于150 filterApples(inventory , (Apple apple) -> "red".equals(apple.getColor()) && apple.getWeight() > 150);}

在这里小结一下:

2018-08-11_041102.png

1.7 举例:方案5

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

// 定义一个函数式接口interface Predicate
{ boolean test(T t);}// 定义一个调用函数式接口的方法public static
List
filter(List
list, Predicate
p) { List
result = new ArrayList<>(); for (T e : list) { if (p.test(e)) { result.add(e); } } return result;}// 使用public static void main(String[] args) { List
inventory = FakeDb.getApples(); List
redList = Filtering.filter(inventory , (Apple apple) -> "red".equals(apple.getColor())); List
nonEmptyList = filter(Arrays.asList("1", "", "2") , (String s) -> !s.isEmpty());}

二、Lambda表达式

2.1 Lambda表达式定义

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

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

2.2 Lambda表达式长什么样子?

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

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

2.3 函数式接口

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

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

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

2.4 Lambda的使用

Predicate 过滤掉列表中的空串

// 定义一个函数式接口interface Predicate
{ boolean test(T t);}// 定义一个调用函数式接口的方法public static
List
filter(List
list, Predicate
p) { List
result = new ArrayList<>(); for (T e : list) { if (p.test(e)) { result.add(e); } } return result;}// 使用public static void main(String[] args) { List
nonEmptyList = filter(Arrays.asList("1", "", "2") , (String s) -> !s.isEmpty());}

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

@FunctionalInterfacepublic interface Consumer
{ void accept(T t);}public static
void forEach(List
list, Consumer
c) { for (T i : list) { c.accept(i); }}public static void main(String[] args) { forEach(Arrays.asList(1, 2, 3, 4), (Integer i) -> System.out.println(i * i));}

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

@FunctionalInterfacepublic interface Function
{ R apply(T t);}public static
List
map(List
list, Function
f) { List
result = new ArrayList<>(); for (T s : list) { result.add(f.apply(s)); } return result;}public static void main(String[] args) { List
result = map(Arrays.asList("1", "22", "333") , (String s) -> s.length());}

2.5 类型推断

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

2.6 方法引用

主要为了简化代码

方法引用,3种

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

构造函数引用

Supplier
c1 = Apple::new; // 指向Apply()构造函数Apple a1 = c1.get();Function
c2 = Apple::new; // 指向Apply(int weight)构造函数Apple a2 = c2.apply(110);BigFunction
c3 = Apple::new;// 指向Apply(String color, Integer weight)Apple c3 = c3.apply("green", 110);

2.7 Lambda实战

根据Apple的重量来排序

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

2.8 复合Lambda表达式

比较器复合

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

谓词复合

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

函数复合

// andThen,composeFunction
f = x -> x + 1;Function
g = x -> x * 2;// g(f(x))Function
h = f.andThen(g);int result = h.apply(1);// f(g(x))Function
h = f.compose(g);int result = h.apply(1);

三、代码

转载于:https://my.oschina.net/yysue/blog/1926508

你可能感兴趣的文章
依赖冲突时的解决方法
查看>>
学习笔记5
查看>>
富人为什么越富,穷人为什么越穷
查看>>
电子商务java b2b b2c o2o平台
查看>>
(五)java spring cloud版b2b2c社交电商spring cloud分布式微服务-路由网关(zuul)
查看>>
零基础学小程序007---小程序获取用户openid
查看>>
两年摸爬滚打 Spring Boot,总结了这 16 条最佳实践
查看>>
Laravel 5 5 使用 Jwt Auth 实现 API 用户认证以及无痛刷新访问令牌
查看>>
专注人工智能未来 十年后百度可能完全不一样?
查看>>
阿里开发者招聘节 | 面试题14:如何实现两金额数据相加(最多小数点两位)...
查看>>
企业分布式微服务云SpringCloud SpringBoot mybatis(八)消息总线(Spring Cloud Bus)
查看>>
logback pattern
查看>>
推荐的JVM参数
查看>>
PHP类UTF8编码内的繁简转换-繁体-简体
查看>>
晒晒工作中的静态文件大小控制制度
查看>>
当存储已成白菜
查看>>
Starting httpd: (13)Permission denied: make_sock: could not bind to address 0.0.0.0:9000
查看>>
vim编辑C++代码寻找标准库中结构的的定义
查看>>
CSS3 Flex布局(容器)
查看>>
Apache 重写机制
查看>>