Java是強型別語言,方法參數都有固定的型別。那麼問題了,Lambda表達式,如果當做是一堆程式碼片段,也會表達一種明確的意圖,這個意圖,姑且可以理解為函數介面。
介面 |
參數 |
傳回類型 |
範例 |
Predicate
T |
boolean |
值等於「Hello」嗎? |
|
Consumer |
T |
void |
輸出一個值 |
Function |
T |
R |
#取得物件的一個屬性 |
##Supplier | None | T | 工廠方法 |
#UnaryOperator | T | #T | 邏輯非(!) |
BinaryOperator | (T, T) | T | #求2個數的和( ) |
#2.4 类型推断
先看一段熟悉的集合代码
ArrayList<Java8Test> list = new ArrayList<>();
在ArrayList中申明了存储的元素的类型,于是在ArrayList<>()这里的类型可以缺省,编译器可以根据左侧(即上文)推断出来。
同理,在lambda表达式也是一样的。
BinaryOperator<Long> addLongs = (x, y) -> x + y;
在上面的表达 式中,我们注意到 (x, y)
这里是没有申明方法的参数类型的,却能执行数学运算 +
。
这里根据函数接口指定的泛型类为Long
,即可推断方法的参数为Long
,然后执行x + y
。
2.5 Lambda小结
Lambda表达式是一个匿名方法,简化了匿名内部类的写法,把模板语法屏蔽,突出业务语句,传达的更像一种行为。
Lambda表达式是有类型的,JDK内置了众多函数接口
Lambda的3段式结构:(...)-> { ...}
3. Stream 流
3.1 简介
流(Stream)是Java8的新特性,是一种使程序员得以站在更高的抽象层次上对集合进行操作。在思路上,类似于SQL的存储过程,有几个步骤:
先定义一些操作的集合,注意:这里只定义,不真正执行
触发执行,获取结果
对结果进一步处理,筛选、打印、使用
其中,第1步的定义操作叫惰性求值,给你套路(返回Stream
),但是不会执行返回结果。
第2步的触发操作叫及早求值,这个人说干就干,立马要结果(返回结果数据)。
第3步的筛选类似SQL的where
子句,对结果进一步的筛选。
3.2 Stream API
Stream
类位于java.util.stream
包,是Java8核心的类之一,拥有众多方法,下面罗列了一些比较重要的方法进行讲解。更多的是抛砖引玉,任何教程都比不上自己的悟性来得爽快,先找点感觉,先掌握基本用法尝试使用起来,慢慢自然就会了。
3.2.1 Stream.of(T… t)
要使用Stream
,那就必须得先创建一个String
类型的Stream
Stream<String> StrStream = Stream.of("a", "b");
3.2.2 Stream.collect(Collector super T, A, R> collector)
使用收集器Collector
将StrStream
转化为熟悉的集合Collection
List<String> collect = StrStream.collect(Collectors.toList());
3.2.2 Stream.map(Function super T, ? extends R> mapper)
所谓map,从字面理解就是映射。这里指的是对象关系的映射,
比如从对象集合映射到属性结合:
List<String> names = Stream.of(new Student("zhangSan"), new Student("liSi"))
.map(student -> student.getName())
.collect(toList());
从小写字母映射到大写字母:
List<String> collected = Stream.of("a", "b", "hello")
.map(string -> string.toUpperCase())
.collect(toList());
将 字符串流 根据空格分割成 字符串数组流
Stream<String> stringStream = Stream.of("Hello Aron.");
Stream<String[]> stringArrayStream = stringStream.map(word -> word.split(" "));
3.2.3 Stream.filter(Predicate super T> predicate)
filter
顾名思义,过滤筛选。这里的参数函数接口是一个条件,筛选出满足条件的元素
// 筛选年龄大于19的学生
List<Student> stu = Stream.of(new Student("zhangSan", 19), new Student("liSi"), 20)
.filter(student -> student.getAge() > 19)
.collect(toList());
3.2.4 Stream.flatMap(Function super T, ? extends Stream extends R>> mapper)
flatMap
扁平化映射,即将数据元素为数组的Stream
转化为单个元素
Stream<String> stringStream = Stream.of("Hello Aron.");
// 返回值为数组
Stream<String[]> stringArrayStream = stringStream.map(word -> word.split(" "));
// flatMap扁平化映射后,元素都合并了
Stream<String> flatResult = stringArrayStream.flatMap(arr -> Arrays.stream(arr))
3.2.5 Stream.max(Comparator super T> comparator)
max
即最大,类似SQL
中的函数max()
,从数据中根据一定的条件筛选出最值
// 筛选年龄最大/小的学生
Stream<Student> studentStream = Stream.of(new Student("zhangSam", 19), new Student("liSi", 20));
Optional<Student> max = studentStream.max(Comparator.comparing(student -> student.getAge()));
// Optional<Student> max = studentStream.min(Comparator.comparing(student -> student.getAge()));
// 年龄最大/小的学生
Student student = max.get();
3.2.7 Sream.reduce(T identity, BinaryOperator binaryOperator)
reduce
操作实现从一组值中生成一个值,上面的max
、min
实际上都是reduce
操作。
参数Identity
表示初始值,
参数binaryOperator
是一个函数接口,表示二元操作,可用于数学运算
// 使用reduce() 求和 (不推荐生产环境使用)
int count = Stream.of(1, 2, 3).reduce(0, (acc, element) -> acc + element);
上面代码,展开reduce()
操作
BinaryOperator<Integer> accumulator = (acc, element) -> acc + element;
int count = accumulator.apply( accumulator.apply(accumulator.apply(0, 1),2), 3);
3.2.8 综合操作
// 查找所有姓张的同学并按字典顺序排序,存储到list
List<Student> newList = studentList.Stream()
.filter(student -> student.getName().startsWith("张"))
.sorted(Comparator.comparing(student -> student.getName())
.collect(toList());