一. 基本概念
二. 串行流和并行流
三. 中间操作 和 最终操作
一. 基本概念
1.1 为什么加入 集合的流式操作
JDK8 的Stream 是一个受到 函数式编程 和 多核时代影响而产生的东西。很多时候我们需要到底层返回数据,上层再对数据进行遍历,进行一些数据统计,但是之前的Java API 中很少有这种方法,这就需要我们自己来 Iterator 来遍历,如果JDK 能够为我们提供一些这种方法,并且能够为我们优化就好了。
所以JDK8加入 了 java.util.stream包,实现了集合的流式操作,流式操作包括集合的过滤,排序,映射等功能。根据流的操作性,又可以分为 串行流 和 并行流。根据操作返回的结果不同,流式操作又分为中间操作和最终操作。大大方便了我们对于集合的操作。
1.2 什么是 流
Stream 不是 集合元素,也不是数据结构,它相当于一个 高级版本的 Iterator,不可以重复遍历里面的数据,像水一样,流过了就一去不复返。它和普通的 Iterator 不同的是,它可以并行遍历,普通的 Iterator 只能是串行,在一个线程中执行。
二. 串行流和并行流:
串行流操作在一个线程中依次完成。并行流在多个线程中完成,主要利用了 JDK7 的 Fork/Join 框架来拆分任务和加速处理。相比串行流,并行流可以很大程度提高程序的效率。
三. 中间操作 和 最终操作
中间操作:
最终操作:
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 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():找到最大值。
Ps1:除了上面介绍的方法,还有如下方法:
map (mapToInt, flatMap 等)、 filter、 distinct、 sorted、 peek、 limit、 skip、 parallel、 sequential、 unordered
forEach、 forEachOrdered、 toArray、 reduce、 collect、 min、 max、 count、 anyMatch、 allMatch、 noneMatch、 findFirst、 findAny、 iterator
anyMatch、 allMatch、 noneMatch、 findFirst、 findAny、 limit
Ps2:在JDK 8 中的 Comparator 接口中,既有 equals 方法,也有 compare 方法,为什么还可以声明为函数式接口?有哪位大神指导麻烦告知一下。
参考:
1. Java 8 新特性概述:http://www.ibm.com/developerworks/cn/java/j-lo-jdk8newfeature/index.html
2. Java 8 中的Stream API 详解:https://www.ibm.com/developerworks/cn/java/j-lo-java8streamapi/