零、 概述

第一部分: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. 单片机ram和rom的区别

    单片机运行时需要调用某个程序/函数/固定数据时就需要读取ROM,然后在RAM中执行这些程序/函数的功能,所产生的临时数据也都存在RAM内,断电后这些临时数据就丢失了.ROM:(Read Only Me ...

  2. 走在 SVG + Low Poly 的路上

    随着 SVG 的发展,艺术家和设计师们把越来越多传统设计行业的东西引入了前端, low poly 就是其中之一.那 low poly 强大在哪呢,大家通过下面的图来感受一下. 恰巧我们产品 Logo ...

  3. angular组件开发

    项目中经常会有一些公共组件,比如header,如果每个页面都写一遍的话显得很冗余,而且不利于维护,这时候我们就会考虑将这些公共部分抽取出来,做成一个单独的组件. 然而angular不是很熟悉啊~怎么啵 ...

  4. CSS揭秘之《背景图案》

    网格 html { background: #58a; background-image: linear-gradient(white 2px, transparent 0), linear-grad ...

  5. java如何读取和遍历properties文件

    在java项目开发过程中,使用properties文件作为配置基本上是必不可少的,很多如系统配置信息,文件上传配置信息等等都是以这种方式进行保存.同时学会操作properties文件也是java基础. ...

  6. Reflect.has检测对象是否拥有某个属性

    Reflect.has({x: 0}, 'x'); // true Reflect.has({x: 0}, 'y'); // false // returns true for properties ...

  7. MySQL---char和varchar的区别

    char和varchar的区别 char表示定长, 即长度固定. varchar表示变长, 即长度可变. 当输入数据的长度小于定义的长度时, char会用空格填充, 而varchar则按照实际长度存储 ...

  8. spring配置数据源(加载properties文件)

    1.在spring中引入properties配置文件需要引入context的命名空间和真实地址 2.然后加载文件 需要注意的是这是采用的是set注入方式,所以name属性值必须是连接池set方法名去掉 ...

  9. String相关API-getBean()方法的使用

    一.使用id //userService是Bean标签中配置的id属性值 UserService service = (UserService) context.getBean("userS ...

  10. linux磁盘概述

    硬盘简史 世界上第一块硬盘出生在1956年,至今已有61年半个多世纪的历史.它由IBM公司制造,世界上第一块硬盘:350RAMAC.盘片直径为24英寸,盘片数为50片,重量则是上百公斤,相当于两个冰箱 ...