Java8新特性:Stream语法详解

你们能够把Stream当成一个高级版本的Iterator。原始版本的Iterator,用户只能一个一个的遍历元素并对其执行某些操做;高级版本的Stream,用户只要给出须要对其包含的元素执行什么操做,好比“过滤掉长度大于10的字符串”、“获取每一个字符串的首字母”等,具体这些操做如何应用到每一个元素上,就给Stream就行了!(这个秘籍,通常人我不告诉他:)css

List<Integer> nums = Lists.newArrayList(1,null,3,4,null,6);
nums.stream().filter(num -> num != null).count();java

list.stream() .filter(student -> student.getSex().equals("G")) .forEach(student -> System.out.println(student.toString()));

List<String> lastStoneList =
                     stoneLine.stream()
                     .filter(s -> s.getWeight() < 500)//挑选出质量小于500g的鹅卵石
                     .sorted(comparing(Stone::getWeight))//按照质量进行排序
                     .map(Stone::getName)//提取知足要求的鹅卵石的名字
                    .collect(toList());//将名字保存到List中
--------------------- 数组

  1. 建立Stream;
  2. 转换Stream,每次转换原有Stream对象不改变,返回一个新的Stream对象(**能够有屡次转换**);
  3. 对Stream进行聚合(Reduce)操做,获取想要的结果;

2.1 使用Stream静态方法来建立Stream的三种方法:

1. of方法:有两个overload方法,一个接受变长参数,一个接口单一值dom

Stream<Integer> integerStream = Stream.of(1, 2, 3, 5);
Stream<String> stringStream = Stream.of("taobao");函数

2. generator方法:生成一个无限长度的Stream,其元素的生成是经过给定的Supplier(这个接口能够当作一个对象的工厂,每次调用返回一个给定类型的对象)测试

Stream.generate(() -> Math.random());
Stream.generate(Math::random);ui

3. iterate方法:也是生成无限长度的Stream,和generator不一样的是,其元素的生成是重复对给定的种子值(seed)调用用户指定函数来生成的。其中包含的元素能够认为是:seed,f(seed),f(f(seed))无限循环。spa

Stream.iterate(1, item -> item + 1).limit(10).forEach(System.out::println);code

3. 转换Stream:

转换Stream其实就是把一个Stream经过某些行为转换成一个新的Stream。Stream接口中定义了几个经常使用的转换方法,下面咱们挑选几个经常使用的转换方法来解释。orm

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

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

3. map: 对于Stream中包含的元素使用给定的转换函数进行转换操做,新生成的Stream只包含转换生成的元素。这个方法有三个对于原始类型的变种方法,分别是:mapToInt,mapToLong和mapToDouble。

4. flatMap:和map相似,不一样的是其每一个元素转换获得的是Stream对象,会把子Stream中的元素压缩到父集合中;

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

6. limit: 对一个Stream进行截断操做,获取其前N个元素,若是原Stream中包含的元素个数小于N,那就获取其全部的元素;

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

Stream的类型和建立方式2:

// 从数组建立 int [] source = {1,2,3,4,5,6}; IntStream s = Arrays.stream(source); // 从集合建立 List list = Arrays.asList(1,2,3,4,5); Stream s2 = list.stream(); // 建立1到10的流 IntStream s3 = IntStream.range(1,10); // 直接建立 Stream s4 = Stream.of("wo", "ai", "?")
// 支持串行并行操做的序列,元素只有double,int,Long类型的流 DoubleStream,IntStream,LongStream。

案例:

// 将元素中的全部偶数累加求和
int[] nums = {2, 3, 4, 5, 6}; System.out.println( Arrays.stream(nums) .map(i -> i % 2 == 0 ? i : 0) .reduce(0, Integer::sum) );


案例三:假设有N条营业数据,前5条是无关的测试数据,中间10条是要参加考核的,参与考核的须要知道其中超过50w(包括50)的数据的交易额平均值,其余不参与考核的忽略// flatMap处理嵌套的list List<List<Integer>> ll = Arrays.asList( Arrays.asList(1, 2, 3), Arrays.asList(11, 22, 33), Arrays.asList(0xF1, 0xF2, 0xF3) ); ll.stream() .flatMap(list -> list.stream()) .map(i -> 2 * i) .forEach(i -> System.out.println(i));
Stream<Integer> trans = Stream.of(11, 9, 2, 13, 1, 2, 99, 54, 23, 66, 70, 23, 46, 50, 100, 10, 24, 18, 19, 2); IntSummaryStatistics all = trans // 前5条跳过,2, 99, 54, 23, 66, 70, 23, 46, 50, 100, 10, 24, 18, 19, 2 .skip(5) // 取10条考核交易 2, 99, 54, 23, 66, 70, 23, 46, 50, 100 .limit(10) // 将50如下的交易剔除 99, 54, 66, 70, 50, 100 .filter(i -> i >= 50) // 转换成数字。若是是IntStream 则不须要转换 .mapToInt(i->i) // 将流的统计结果放入包装对象中 .summaryStatistics(); // 交易总量 439w,平均值为439/6 System.out.println(all.getAverage());

Stream流的特性:

1.不能重复使用。

Stream<Integer> trans = Stream.of(11, 9, 2); trans.forEach(i -> System.out.println(i)); trans.reduce(0, Integer::sum); 

当我第二次使用trans时,报错了。


 

2.验证流延迟操做:流只要在终止操做(及早求值)时,才会对数据统一作操做,在没有遇到求值操做的时候,惰性操做代码不会被执行。

Stream<Integer> trans = Stream.of(11, 70, 23, 46, 50, 100, 10, 24, 18, 19, 2); trans.map(i->{ System.out.println(i); return i; }); 
 
3.不影响源数据。