您的位置:首页 > 编程语言 > Java开发

Java JVM(九):JDK8的集合流式操作

2015-09-10 11:25 471 查看
一. 基本概念
二. 串行流和并行流
三. 中间操作 和 最终操作

一. 基本概念

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():找到最大值。

            

Ps1:除了上面介绍的方法,还有如下方法:

Intermediate:

             
  map (mapToInt, flatMap 等)、 filter、 distinct、 sorted、 peek、 limit、 skip、 parallel、 sequential、 unordered

Terminal:

             
  forEach、 forEachOrdered、 toArray、 reduce、 collect、 min、 max、 count、 anyMatch、 allMatch、 noneMatch、 findFirst、
findAny、 iterator

Short-circuiting:

             
  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/
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息