java8新特性:Lambda 表达式

主要内容

1. Lambda 表达式
2. 函数式接口
3. 方法引用与构造器引用
4. Stream API
5. 其他新特性

Java 8新特性简介

速度更快
代码更少(增加了新的语法 Lambda 表达式)
强大的 Stream API
便于并行
最大化减少空指针异常 Optional

1、Lambda表达式

Lambda 是一个匿名函数

在Java 语言中引入了一个新的语法元
素和操作符。这个操作符为 “->” , 该操作符被称
为 Lambda 操作符或剪头操作符。它将 Lambda 分为
两个部分:
左侧:指定了 Lambda 表达式需要的所有参数
右侧:指定了 Lambda 体,即 Lambda 表达式要执行
的功能。

2、Lambda 表达式语法

语法格式一:无参,无返回值,Lambda 体只需一条语句

Runnable r1 = () → System.out.println("hello world");

 

语法格式二:Lambda 需要一个参数

Consumer fun = (args) → System.out.println(args);

 

语法格式三:Lambda 只需要一个参数时,参数的小括号可以省略

Consumer fun = args → System.out.println(args);

 

语法格式四:Lambda 需要两个参数,并且有返回值

BinaryOperator bo = (x, y) → {

System.out.println("hello world");

reurn x + y;

}

 

语法格式五:当 Lambda 体只有一条语句时,return 与大括号可以省略

BinaryOperator bo = (x, y) → x + y;

 

语法格式六:数据类型可以省略,因为可由编译器推断得出,称为“类型推断”

BinaryOperator bo = (Longx, Long y) → {

System.out.println("hello world");

reurn x + y;

}

类型推断:
上述 Lambda 表达式中的参数类型都是由编译器推断
得出的。Lambda 表达式中无需指定类型,程序依然可
以编译,这是因为 javac 根据程序的上下文,在后台
推断出了参数的类型。Lambda 表达式的类型依赖于上
下文环境,是由编译器推断出来的。这就是所谓的
“类型推断”

2、函数式接口

(1) 只包含一个抽象方法的接口,称为函数式接口。
(2) 你可以通过 Lambda 表达式来创建该接口的对象。(若 Lambda 
表达式抛出一个受检异常,那么该异常需要在目标接口的抽象方
法上进行声明)。
(3) 我们可以在任意函数式接口上使用 @FunctionalInterface 注解,
这样做可以检查它是否是一个函数式接口,同时 javadoc 也会包
含一条声明,说明这个接口是一个函数式接口。

自定义函数式接口

@FounctionalInterface

public interface MyNumber {

public double getValue();

}

@FounctionalInterface

public interface MyNumber {

public T getValue(T t);

}

作为参数传递 Lambda 表达式

ListenableFuture speechTechniqueMacdFuture = executorService.submit( () -> 1+1);

3、Java 内置四大核心函数式接口

 

函数式接

参数类型

返回类型

用途

Consumer
消费型接口
 

T void 对类型为T的对象应用操
作,包含方法:
void accept(T t)
Supplier供给型 无 

返回类型为T的对象,包
含方法:T get();

Function函数型 R 对类型为T的对象应用操作,并返回结果。结果是R类型的对象。包含方法:R apply(T t)
Predicate断定型 T boolea 确定类型为T的对象是否满足某约束,并返回boolean 值。包含方法boolean test(T t)

 

4、方法引用与构造器引用

方法引用:使用操作符 “::” 将方法名和对象或类的名字分隔开来

对象::实例方法

类::静态方法

类::实例

 

Function in = Integer[]::new;

.stream().sorted(Comparator.comparingLong(ConditionAllVO::getStockTotalCount).reversed()).collect(Collectors.toList()))

5、强大的 Stream API

是数据渠道,用于操作数据源(集合、数组等)所生成的元素序列“集合讲的是数据,流讲的是计算

注意:

(1)Stream 自己不会存储元素。

(2)Stream 不会改变源对象。相反,他们会返回一个持有结果的新Stream。

(3)Stream 操作是延迟执行的。这意味着他们会等到需要结果的时候才执行

 

Lists.newArrayList().stream() : 返回一个顺序流
Lists.newArrayList().parallelStream() : 返回一个并行流

Arrays.stream(new Integer[1]).count();

 

Stream stream = Stream.of(Lists.newArrayList());

Stream 的中间操作

多个中间操作可以连接起来形成一个流水线,除非流水线上触发终止操作,

否则中间操作不会执行任何的处理!而在终止操作时一次性全部处理,称为“惰性求值”。

筛选

 

方 法

描述

filter(Predicate p)

接收 Lambda , 从流中排除某些元素。

distinct() 筛选,通过流所生成元素的 hashCode() 和 equals() 去除重复
limit(long maxSize) 截断流,使其元素不超过给定数
skip(long n) 跳过元素,返回一个扔掉了前 n 个元素的流。若流中元素不足 n 个,则返回一个空流。与 limit(n)  互补

映射

 

方 法

描述

map(Function f) 接收一个函数作为参数,该函数会被应用到每个素上,并将其映射成一个新的
mapToDouble(ToDoubleFunction f)

接收一个函数作为参数,该函数会被应用到每个元
素上,产生一个新的 DoubleStream。

mapToInt(ToIntFunction f) 接收一个函数作为参数,该函数会被应用到每个元素上,产生一个新的 IntStream
mapToLong(ToLongFunction f) 接收一个函数作为参数,该函数会被应用到每个元素上,产生一个新的 LongStream

flatMap(Function f)

flatMapToDouble(Function f)

flatMapToInt(Function f)

flatMapToLong(Function f)

接收一个函数作为参数,将流中的每个值都换成另一个流,然后把所有流连接成一个流

排序

 

方 法

描述

sorted() 产生一个新流,其中按自然顺序
sorted(Comparator comp) 产生一个新流,其中按比较器顺序

 

查找与匹配

 

方 法

描述

allMatch(Predicate p) 检查是否匹配所有元素
anyMatch(Predicate p) 检查是否至少匹配一个元素
noneMatch(Predicate p) 检查是否没有匹配所有元素
findFirst() 返回第一个元素
findAny() 返回当前流中的任意元素
count() 返回流中元素个数
max(Comparator c) 返回流中最大值
min(Comparator c) 返回流中最小值
forEach(Consumer c) 内部迭代(使用 Collection 接口需要用户去做迭代,称为外部迭代。相反,Stream API 使用内部迭代——它帮你把迭代做了

 

归约

方 法

描述

reduce(T iden, BinaryOperator b)

可以将流中元素反复结合起来,得到一个值。返回 T
reduce(BinaryOperator b) 可以将流中元素反复结合起来,得到一个值。返回 Optional

收集

方 法

描述

collect(Collector c) 将流转换为其他形式。接收一个 Collector接口的实现,用于给Stream中元素做汇总的方法

 

方法

返回类型

作用

toList List 把流中元素收集到List:list.stream().collect(Collectors.toList());
toSet Set 把流中元素收集到Set:list.stream().collect(Collectors.toSet());

toCollection

Collection 把流中元素收集到创建的集合:list.stream().collect(Collectors.toCollection(ArrayList::new));
counting Long

计算流中元素的个数:list.stream().collect(Collectors.counting());

summingInt Integer 对流中元素的整数属性求和:list.stream().collect(Collectors.summingInt(类名::属性名));
averagingInt Double 计算流中元素Integer属性的平均值:list.stream().collect(Collectors.averagingInt(类名::属性名));

summarizingInt

summarizingLong

summarizingDouble

IntSummaryStatistics

收集流中Integer属性的统计值:list.stream().collect(Collectors.summarizingInt(类名::属性名));

一次性得到元素个数、总和、均值、最大值、最小值

joining

String

连接流中每个字符串:
list.stream().map(类名::属性名).collect(Collectors.joining());

maxBy

Optional 根据比较器选择最大值:
list.stream().collect(Collectors.maxBy(comparingInt(类名::属性名)));
minBy Optional 根据比较器选择最小值:list.stream().collect(Collectors.minBy(comparingInt(类名::属性名))
reducing 归约产生的类型

从一个作为累加器的初始值开始,利用BinaryOperator与流中元素逐个结合,从而归约成单个值

list.stream().collect(Collectors.reducing(0, 类名::属性名, Integer::sum));

collectingAndThen 转换函数返回的类型 包裹另一个收集器,对其结果转换函数:list.stream().collect(Collectors.collectingAndThen(Collectors.toList(), List::size));
groupingBy 根据 Map

某属性值对流分组,属性为K,结果为V:

list.stream().collect(Collectors.groupingBy( 类名::属性名));

partitioningBy Map> 根据true或false进行分区:list.stream().collect(Collectors.partitioningBy(类名::属性名)

 

6、并行流与串行流

并行流就是把一个内容分成多个数据块,并用不同的线程分
别处理每个数据块的流。
Java 8 中将并行进行了优化,我们可以很容易的对数据进行并
行操作。Stream API 可以声明性地通过 parallel() 与
sequential() 在并行流与顺序流之间进行切换。

7、Optional 类

Optional 类(java.util.Optional) 是一个容器类,代表一个值存在或不存在,
原来用 null 表示一个值不存在,现在 Optional 可以更好的表达这个概念。并且
可以避免空指针异常。
常用方法:
Optional.of(T t) : 创建一个 Optional 实例
Optional.empty() : 创建一个空的 Optional 实例
Optional.ofNullable(T t):若 t 不为 null,创建 Optional 实例,否则创建空实例
isPresent() : 判断是否包含值
orElse(T t) : 如果调用对象包含值,返回该值,否则返回t
orElseGet(Supplier s) :如果调用对象包含值,返回该值,否则返回 s 获取的值
map(Function f): 如果有值对其处理,并返回处理后的Optional,否则返回 Optional.empty()
flatMap(Function mapper):与 map 类似,要求返回值必须是Optional

QQ学习交流,资料共享群:696647351,期望大家一起学习讨论

你可能感兴趣的:(Java8新特性)