须要Lambda表达式的缘由主要有三个:java
1. 更紧凑的代码编程
2. 经过提供额外的功能对方法的功能进行修改的能力数据结构
3. 更好地支持多核处理多线程
更紧凑的代码并发
Lambda表达式以一种简洁的方式去实现仅有一个方法的Java类。框架
例如,若是代码中有大量的匿名内部类–诸如用于UI应用中的监听器与处理器实现,以及用于并发应用中的Callable与Runnable实现–在使用了Lambda表达式以后,将使代码变得很是短,且更易于理解。函数式编程
修改方法的能力函数
有时,方法不具有咱们想要的一些功能。例如,Collection接口中的contains()方法只有当传入的对象确实存在于该集合对象中时才会返回true。但咱们没法去干预该方法的功能,好比,若使用不一样的大小写方案也能够认为正在查找的字符串存在于这个集合对象中,咱们但愿此时contains()方法也能返回true。优化
简单点儿说,咱们所指望作的就是”将咱们本身的新代码传入”已有的方法中,而后再调用这个传进去的代码。Lambda表达式提供了一种很好的途径来表明这种被传入已有方法且应该还会被回调的代码。编码
更好地支持多核处理
当今的CPU具有多个内核。这就意味着,多线程程序可以真正地被并行执行,这彻底不一样于在单核CPU中使用时间共享这种方式。经过在Java中支持函数式编程语法,Lambda表达式能帮助你编写简单的代码去高效地应用这些CPU内核。
例如,你可以并行地操控大集合对象,经过利用并行编程模式,如过滤、映射和化简(后面将会很快接触到这些模式),就可以使用到CPU中全部可用的硬件线程。
一. 基本概念
1.1 为何加入 集合的流式操做
JDK8 的Stream 是一个受到 函数式编程 和 多核时代影响而产生的东西。不少时候咱们须要到底层返回数据,上层再对数据进行遍历,进行一些数据统计,可是以前的Java API 中不多有这种方法,这就须要咱们本身来 Iterator 来遍历,若是JDK 可以为咱们提供一些这种方法,而且可以为咱们优化就行了。
因此JDK8加入 了 java.util.stream包,实现了集合的流式操做,流式操做包括集合的过滤,排序,映射等功能。根据流的操做性,又能够分为 串行流 和 并行流。根据操做返回的结果不一样,流式操做又分为中间操做和最终操做。大大方便了咱们对于集合的操做。
最终操做:返回一特定类型的结果。
中间操做:返回流自己。
1.2 什么是 流
Stream 不是 集合元素,也不是数据结构,它至关于一个 高级版本的 Iterator,不能够重复遍历里面的数据,像水同样,流过了就一去不复返。它和普通的 Iterator 不一样的是,它能够并行遍历,普通的 Iterator 只能是串行,在一个线程中执行。
二. 串行流和并行流:
串行流操做在一个线程中依次完成。并行流在多个线程中完成,主要利用了 JDK7 的 Fork/Join 框架来拆分任务和加速处理。相比串行流,并行流能够很大程度提升程序的效率。
三. 中间操做 和 最终操做
中间操做:
filter(): 对元素进行过滤
sorted():对元素排序
map():元素映射
distinct():去除重复的元素
最终操做:
forEach():遍历每一个元素。
reduce():把Stream 元素组合起来。例如,字符串拼接,数值的 sum,min,max ,average 都是特殊的 reduce。
collect():返回一个新的集合。
min():找到最小值。
max():找到最大值。
3.1 filter() 对元素进行过滤
Demo(有一链表,{1,2,3,4,5},把偶数过滤掉):
public class Test { public static void main(String[] args) throws InterruptedException { List list = new ArrayList(); for(int i = 1 ; i <= 5; ++i){ list.add(i); } list.stream().filter(param -> (int)param % 2 == 1) .forEach(System.out::println); } }
输出:
1 3 5
3.2 sorted() 对元素进行排序
Demo(有一链表,{2,3,1,5,4},从小到大排序):
public class Test { public static void main(String[] args) throws InterruptedException { List list = new ArrayList(); list.add(2); list.add(3); list.add(1); list.add(5); list.add(4); list.stream().sorted().forEach(System.out::println); } }
输出:
1 2 3 4 5
Ps1: 此时为升序,那么有时候咱们可能会须要到降序,此时作法能够以下:
流除了提供默认的升序 sorted() 方法,也提供了:
Stream<T> sorted(Comparator<? super T> comparator);
那么,自定义比较函数便可,以下代码:
public class Test { public static void main(String[] args) throws InterruptedException { List list = new ArrayList(); list.add(2); list.add(3); list.add(1); list.add(5); list.add(4); // list.stream().sorted().forEach(System.out::println); list.stream().sorted( (param1,param2) -> ((int)param1 < (int)param2 ? 1 : -1 ) ) .forEach(System.out::println); } }
输出为:
5 4 3 2 1
3.3 map() 元素映射
也就是说,原来的链表的每一个元素能够按照规则变成相应的元素。
Demo(链表 (1,0),变成 true,false):
public class Test { public static void main(String[] args) throws InterruptedException { List list = new ArrayList(); list.add(1); list.add(0); list.stream().map( param -> (int)param == 1 ? true:false ) .forEach(System.out::println); } }
输出:
true false
3.4 distinct() 去除重复元素
Demo:
public class Test { public static void main(String[] args) throws InterruptedException { List list = new ArrayList(); list.add(1); list.add(1); list.add(0); list.stream().distinct().forEach(System.out::println); } }
3.5 reduce() :把Stream 元素组合起来。
Demo(从1加到5):
public class Test { public static void main(String[] args) throws InterruptedException { List list = new ArrayList(); list.add(1); list.add(2); list.add(3); list.add(4); list.add(5); System.out.println( list.stream().reduce((param1,param2) ->(int)param1 + (int)param2 ).get()); } }
注意,reduce() 返回一个 Optional 类型的对象,能够经过 get() 方法得到值。
3.6 collect() :返回一个新的集合
Demo(先把 list 集合的 奇数去掉,而后把剩下的偶数返回到 _list 集合中):
public class Test { public static void main(String[] args) throws InterruptedException { List list = new ArrayList(); list.add(1); list.add(2); list.add(3); list.add(4); list.add(5); List _list = (List) list.stream().filter((param) -> (int)param % 2 == 0) .collect(Collectors.toList()); _list.forEach(System.out::println); } }
输出:
2 4
3.7 min(),max() 找到最大值最小值
public class Test { public static void main(String[] args) throws InterruptedException { List list = new ArrayList(); list.add(1); list.add(2); list.add(3); list.add(4); list.add(5); System.out.println(list.stream().min( (param1,param2) -> (int)param1 > (int)param2 ? 1:-1 ).get()); System.out.println(list.stream().max( (param1,param2) -> (int)param1 > (int)param2 ? 1:-1 ).get()); } }
注意, min(),max() 方法也是返回 Optional 对象, 能够经过 get() 方法返回值。 总结: 1. 流式操做的引入:提升执行效率(并行),方便编码(有不少API 可用),提升可读性。 2. 流的分类:能够分为串行流和并行流;对于操做:能够分为中间操做和最终操做 3. 流API: 中间操做: filter(): 对元素进行过滤; sorted():对元素排序; map():元素映射; distinct():去除重复的元素 。 最终操做: forEach():遍历每一个元素; reduce():把Stream 元素组合起来。例如,字符串拼接,数值的 sum,min,max ,average 都是特殊的 reduce。 collect():返回一个新的集合。 min():找到最小值。 max():找到最大值。