零、 概述

第一部分: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<Apple> filterGreenApples(List<Apple> inventory) {
List<Apple> result = new ArrayList<>();
for (Apple apple : inventory) {
if ("green".equals(apple.getColor())) {
result.add(apple);
}
}
return result;
} // 可筛选任意颜色苹果,把颜色作为参数
public static List<Apple> filterGreenApplesByColor(List<Apple> inventory, String color) {
List<Apple> result = new ArrayList<>();
for (Apple apple : inventory) {
if (apple.getColor().equals(apple.getColor())) {
result.add(apple);
}
}
return result;
}
// 筛选不同重量的苹果
public static List<Apple> filterGreenApplesByWeight(List<Apple> inventory, int weight) {
List<Apple> result = new ArrayList<>();
for (Apple apple : inventory) {
if (apple.getWeight() > weight) {
result.add(apple);
}
}
return result;
} // 写一个方法同时支持筛选颜色和重量
public static List<Apple> filterGreenApples(List<Apple> inventory, String color, int weight
, boolean filterColorFlag) {
List<Apple> 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());
}
} // 重量大于150
class AppleHeavyWeightPredicate implements ApplePredicate {
@Override
public boolean test(Apple apple) {
return apple.getWeight() > 150;
}
} // 红色且重量大于150
class AppleRedAndHeavyPredicate implements ApplePredicate {
@Override
public boolean test(Apple apple) {
return "red".equals(apple.getColor()) && apple.getWeight() > 150;
}
} // 实现
public static List<Apple> filterApples(List<Apple> inventory, ApplePredicate p) {
List<Apple> result = new ArrayList<>();
for (Apple apple : inventory) {
if (p.test(apple)) {
result.add(apple);
}
}
return result;
} public void test() {
List<Apple> 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<Apple> filterApples(List<Apple> inventory, ApplePredicate p) {
List<Apple> result = new ArrayList<>();
for (Apple apple : inventory) {
if (p.test(apple)) {
result.add(apple);
}
}
return result;
} public static void main(String[] args) {
List<Apple> 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<Apple> filterApples(List<Apple> inventory, ApplePredicate p) {
List<Apple> result = new ArrayList<>();
for (Apple apple : inventory) {
if (p.test(apple)) {
result.add(apple);
}
}
return result;
} public static void main(String[] args) {
List<Apple> 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);
}

在这里小结一下:

1.7 举例:方案5

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

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

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

@FunctionalInterface
public interface Consumer<T> {
void accept(T t);
} public static <T> void forEach(List<T> list, Consumer<T> 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** 返回列表中每个元素的长度

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

2.5 类型推断

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

2.6 方法引用

主要为了简化代码

方法引用,3种

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

构造函数引用

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

2.7 Lambda实战

根据Apple的重量来排序

// 行为参数化,下面是通过不同方式传递这个行为的
// 1.使用对象
public class AppleComparator implements Comparator<Apple> {
public int compare(Apple a1, Apple a2) {
return a1.getWeight().compareTo(a2.getWeight());
}
}
inventory.sort(new AppleComparator()); // 2.使用匿名类
inventory.sort(new Comparator<Apple>(){
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<Apple> 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,compose

Function<Integer, Integer> f = x -> x + 1;
Function<Integer, Integer> g = x -> x * 2; // g(f(x))
Function<Integer, Integer> h = f.andThen(g);
int result = h.apply(1); // f(g(x))
Function<Integer, Integer> h = f.compose(g);
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. Vue2的右键弹出菜单(vue-contextmenu)

    给大家推荐一个基于Vue2的右键弹出菜单插件,支持单一SPA页面以及可以在循环绑定中使用. 项目地址为:https://github.com/chIIC/vue-...demo1: 父组件绑定右键事件 ...

  2. Amaze UI 模版中心上线丨十几款高质量优秀模版免费提供!

    Amaze UI模版中心终于上线了,目前汇聚了包含企业门户.新闻资讯.管理后台等多个领域的模版,全都可以免费下载. Amaze UI模版中心后续还会增加更多的模版以及领域,请各位持续关注. 模版中心的 ...

  3. zhilizhili-ui 荡平ie8910 还我前端清净地

    zhilizhili-ui 给大家带来一个目前最新版本的ie8方案 特色 flexbox部分功能 vw vh calc部分功能 angular1.4 todo avalon是因为无法和polyfill ...

  4. node+express+mysql 实现登陆注册

    基于 node.express.mysql 实现的登录注册. 1.`首先在终端中 安装 node .` 2.`通过npm install express -g 命令全局安装 express`. 3.` ...

  5. C#复杂XML反序列化为实体对象两种方式

    前言 今天主要讲的是如何把通过接口获取到的Xml数据转换成(反序列化)我们想要的实体对象,当然Xml反序列化和Json反序列化的方式基本上都是大同小异.都是我们事先定义好对应的对应的Xml实体模型,不 ...

  6. AS的不同布局

    AndroidStudio里面支持的布局有挺多种的,但是最最重要的是RelativeLayout(相对布局)和LinearLayout(线性布局),熟练掌握这两种布局也非常够用了,当然还有FrameL ...

  7. sql server总结二

    一些常用查询 Insert into 表(字段一,字段二,字段三,---) values(插入一,插入二,插入三,----) Update 表 set 字段= where 字段= Delete fro ...

  8. /application/zabbix/sbin/zabbix_server: error while loading shared libraries: libmysqlclient.so.20: cannot open shared object file: No such file or directory

    在启动/usr/local/zabbix/sbin/zabbix_server 时报错如下 此时需要配置一个软连接指向该位置. ln -s /usr/local/mysql/lib/libmysqlc ...

  9. drf的JWT认证

    JWT认证(5星) token发展史 在用户注册或登录后,我们想记录用户的登录状态,或者为用户创建身份认证的凭证.我们不再使用Session认证机制,而使用Json Web Token(本质就是tok ...

  10. 前端CSS基础

    一:CSS 1.什么是CSS? CSS(Cascading Style Sheet,层叠样式表)定义如何显示HTML元素. 当浏览器读到一个样式表,它就会按照这个样式表来对文档进行格式化(渲染). C ...