Java 8 Streams的简单使用方法

Java 8 Streams的简单使用方法

 1 package JDK8Test;
 2 import java.util.ArrayList;
 3 
 4 public class Main 
 5 {
 6     public static void main(String[] args) 
 7     {
 8         ArrayList<Integer> nums=new ArrayList<Integer>();
 9         nums.add(1);
10         nums.add(null);
11         nums.add(3);
12         nums.add(4);
13         nums.add(null);
14         nums.add(6);
15         int n=(int)nums.stream().filter(num->num!=null).count();
16         System.out.println(n);//4
17     }
18 }

  上面这段代码是获取一个List中,元素不为null的个数。

  

  

  红色框中的语句是一个Stream的生命开始的地方,负责创建一个Stream实例;绿色框中的语句是赋予Stream灵魂的地方,把一个Stream转换成另外一个Stream,红框的语句生成的是一个包含所有nums变量的Stream,通过绿框的filter方法以后,重新生成了一个过滤掉原nums列表所有null以后的Stream;蓝色框中的语句是丰收的地方,把Stream的里面包含的内容按照某种算法来汇聚成一个值。  

  使用Stream的基本步骤:

  1.创建Stream;

  2.转换Stream,每次转换原有Stream对象不改变,返回一个新的Stream对象(可以有多次转换);

  3.对Stream进行聚合操作,获取想要的结果;

  怎么得到Stream:

  ①使用Stream静态方法来创建Stream:

  of方法:有两个重载方法,一个接受变长参数,一个接受单一值 
  Stream integerStream = Stream.of(1, 2, 3, 5);
  Stream stringStream = Stream.of(“taobao”);

  ②通过Collection接口的默认方法stream(),把一个Collection对象转换成Stream。

  转换Stream:

  转换Stream其实就是把一个Stream通过某些行为转换成一个新的Stream。

  ①distinct: 对于Stream中包含的元素进行去重操作(去重逻辑依赖元素的equals方法),新生成的Stream中没有重复的元素;

  ②filter: 对于Stream中包含的元素使用给定的过滤函数进行过滤操作,新生成的Stream只包含符合条件的元素;

  

  

  ③map: 对于Stream中包含的元素使用给定的转换函数进行转换操作,新生成的Stream只包含转换生成的元素。这个方法有三个对于原始类型的变种方法,分别是:mapToInt,mapToLong和mapToDouble。这三个方法也比较好理解,比如mapToInt就是把原始Stream转换成一个新的Stream,这个新生成的Stream中的元素都是int类型。
  

  例子:

 1 package JDK8Test;
 2 import java.util.*;
 3 import java.util.Arrays;
 4 import java.util.stream.Collectors;
 5 
 6 public class Main 
 7 {
 8     public static void main(String[] args) 
 9     {
10         List<String> list=Arrays.asList(new String[] {"Ni","Hao","Lambda"});
11         List<String> list2=list.stream().map(item->item.toLowerCase()).collect(Collectors.toList());
12         System.out.println(list2);
13     }//[ni, hao, lambda]
14 }    

  这段代码就是对一个字符串的列表,把其中包含的每个字符串都转换成全小写的字符串。注意代码第四行的map方法调用,这里map方法就是接受了一个lambda表达式。

 1 package JDK8Test;
 2 import java.util.*;
 3 import java.util.Arrays;
 4 import java.util.stream.Collectors;
 5 
 6 public class Main 
 7 {
 8     public static void main(String[] args) 
 9     {
10         List<String> list=Arrays.asList(new String[] {"Ni","Hao","Lambda"});
11         List<String> list2=list.stream().map(item->{return "lambda:"+item;}).collect(Collectors.toList());
12         list2.forEach(System.out::println);
13     }
14 }
15 /*
16 lambda:Ni
17 lambda:Hao
18 lambda:Lambda
19 */

  集合的forEach()方法,对集合进行遍历,小括号中的方法就是应用到集合中每个元素的身上,以达到遍历的目的。

 1 package JDK8Test;
 2 import java.util.*;
 3 import java.util.Arrays;
 4 import java.util.stream.Collectors;
 5 
 6 public class Main 
 7 {
 8     public static void main(String[] args) 
 9     {
10         String waibu="lambda:";
11         List<String> proStrs=Arrays.asList(new String[] {"Ni","Hao","Lambda"});
12         List<String> exeStrs=proStrs.stream().map(chuandi->{
13             long zidingyi=System.currentTimeMillis();
14             return waibu+chuandi+"------:"+zidingyi;
15         }).collect(Collectors.toList());
16         exeStrs.forEach(System.out::println);
17     }
18 }
19 /*
20 lambda:Ni------:1559118070052
21 lambda:Hao------:1559118070052
22 lambda:Lambda------:1559118070052
23 */

  

  lambda表达式可以访问给它传递的变量,访问自己内部定义的变量,同时也能访问它外部的变量。 不过lambda表达式访问外部变量有一个非常重要的限制:变量不可变(只是引用不可变,而不是真正的不可变)。 当在表达式内部修改waibu = waibu + " ";时,IDE就会报错。因为变量waibu被lambda表达式引用,所以编译器会隐式的把其当成final来处理。
  以前Java的匿名内部类在访问外部变量的时候,外部变量必须用final修饰。现在java8对这个限制做了优化,可以不用显示使用final修饰,但是编译器隐式当成final来处理。

  ④peek: 生成一个包含原Stream的所有元素的新Stream,同时会提供一个消费函数(Consumer实例),新Stream每个元素被消费的时候都会执行给定的消费函数;

  

  ⑤limit: 对一个Stream进行截断操作,获取其前N个元素,如果原Stream中包含的元素个数小于N,那就获取其所有的元素;

  

  ⑥skip: 返回一个丢弃原Stream的前N个元素后剩下元素组成的新Stream,如果原Stream中包含的元素个数小于N,那么返回空Stream;

  

  汇聚Stream:

  

  汇聚操作(也称为折叠)接受一个元素序列为输入,反复使用某个合并操作,把序列中的元素合并成一个汇总的结果。比如查找一个数字列表的总和或者最大值,或者把这些数字累积成一个List对象。Stream接口有一些通用的汇聚操作,比如reduce()和collect();也有一些特定用途的汇聚操作,比如sum(),max()和count()。注意:sum方法不是所有的Stream对象都有的,只有IntStream、LongStream和DoubleStream实例才有。

  ①reduce():把 Stream 元素组合起来。它提供一个起始值(种子),然后依照运算规则(BinaryOperator),返回单个的结果值,并且reduce操作每处理一个元素总是创建一个新值。

  

  ②collect:正如其名字显示的,它可以把Stream中的所有元素收集到一个结果容器中(比如Collection)。

  Java 8还给我们提供了Collector的工具类——Collectors,其中已经定义了一些静态工厂方法,比如Collectors.toCollection()收集到Collection中, Collectors.toList()收集到List中和Collectors.toSet()收集到Set中。
  List numsWithoutNull = nums.stream().filter(num -> num != null).collect(Collectors.toList());

  ③count方法:获取Stream中元素的个数。

  – 搜索相关
  – allMatch:是不是Stream中的所有元素都满足给定的匹配条件
  – anyMatch:Stream中是否存在任何一个元素满足匹配条件
  – findFirst: 返回Stream中的第一个元素,如果Stream为空,返回空Optional
  – noneMatch:是不是Stream中的所有元素都不满足给定的匹配条件
  – max和min:使用给定的比较器(Operator),返回Stream中的最大|最小值
  下面给出allMatch和max的例子:

 1 package JDK8Test;
 2 import java.util.*;
 3 
 4 
 5 public class Main 
 6 {
 7     public static void main(String[] args) 
 8     {
 9         ArrayList<Integer> nums=new ArrayList<Integer>();
10         nums.add(1);
11         nums.add(null);
12         nums.add(3);
13         nums.add(4);
14         nums.add(null);
15         nums.add(6);
16         System.out.println(nums.stream().filter(item->item!=null).allMatch(item->item<100));
17     }
18 }
19 /*
20 true
21 */

  以上代码,判断nums列表里的不为null元素是否都满足“小于100“这个条件,输出为true。

 1 package JDK8Test;
 2 import java.util.*;
 3 
 4 
 5 public class Main 
 6 {
 7     public static void main(String[] args) 
 8     {
 9         ArrayList<Integer> nums=new ArrayList<Integer>();
10         nums.add(1);
11         nums.add(null);
12         nums.add(3);
13         nums.add(4);
14         nums.add(null);
15         nums.add(6);
16         nums.stream().filter(item->item!=null).max((o1,o2)->o1-o2).ifPresent(System.out::println);
17     }
18 }
19 /*
20 6
21 */

  以上代码,先把nums里为null的元素过滤掉,然后输出nums里元素的最大值。输出为6。

 

 

 

  

 

posted @ 2019-05-29 16:35  白春雨  阅读(1378)  评论(0编辑  收藏  举报