【Java8】数值流

出现的情景

        获取年龄,想直接通过如下代码获取年龄的总和

【Java8】数值流_第1张图片

但是这样是不支持的。问题在于map方法生成的是Stream。虽然元素是Interger类,但是Stream 接口中没有定义sum方法。原因大概是,对于Stream 这样的对象,
定义sum是没有意义的。Stream APi 还提供了原始类特化,专门用来处理数值流的方法。

原始类类型特化

    Java 引入了三个原始类型特化接口来解决这个问题,IntStream ,DoubleStream,LongStream 分别将流元素转化为 int ,double,long,从而避免了暗含的装箱成本。每个接口都提供了进行数值计算的方法,比如sum,max方法等,还有在必要
时候,再把他们转化为对象流的方法。重点记住,特化的原因是解决装箱造成的复杂性。即类似于int和Integer的效率差异。

1.映射到数值流

   将流转化为特化流,常用的方法 mapToInt,mapToDouble,mapToLong,这些方法和前面说的map方法的工作方式一样,只是返回的是一个特化的数值流,而不是
   stream,   此外,还支持max,min,average等方法。

 @Test
    public void getUserInfoTest() {
        List initStudentList = StudentEntity.createInitStudentList();

        int sum = initStudentList.stream() //返回的是stream
                .mapToInt(StudentEntity::getAge) //返回的是IntStream
                .sum(); //调用IntStream 中定义的sum方法,求和;如果流是空,默认返回0
        logger.info("年龄和是:{}",sum );
    }

2.转换回对象流

    //将stream 转化为数值流
        IntStream intStream = initStudentList.stream().mapToInt(StudentEntity::getAge);
        //将数值流转化为Stream
        Stream boxed = intStream.boxed();

3.默认值 optionalInt

     对于不存在的值,可以使用OptionInt,OptionDouble,OptionLong
      例如求最大值的时候, 会返回一个optionalInt

  @Test
    public void testOption() {
        List initStudentList = StudentEntity.createInitStudentList();
        OptionalInt maxOption = initStudentList.stream()
                .mapToInt(StudentEntity::getAge)
                .max();
        //如果没有最大值,可以提供一个默认的
        int max = maxOption.orElse(1);
        logger.info("最大值是:{}", max);
    }

4,数值范围


   加入要生成1 到 100 的所有数值,Java8 引入了可以用于IntStream 和LongStream的静态方法,生成范围是:
   rang 和rangeClosed ,这两个方法都是第一个参数是起始值,第二个参数是结束值,但是range是不包含结束值,rangeClosed
   包含结束值。

 IntStream.of(5, 3, 2, 4, 1)
                .filter(id -> id > 2)
                .peek(value -> logger.info("element is:{}", value))
                .mapToObj(String::valueOf)
                .forEach(va -> logger.info("peek:{}", va));
 @Test
    public void testIntStream() {
        // Objects.requireNonNull(action);
        IntStream.of(5, 3, 2, 4, 1)
                .filter(id -> id > 2)
                .peek(value -> logger.info("element is:{}", value))
                .mapToObj(String::valueOf)
                .forEach(va -> logger.info("peek:{}", va));

        IntStream.rangeClosed(0, 10)
                .skip(5)
                .forEach(id -> logger.info("skip之后:{}", id));
        // skip之后:5
        //skip之后:6
        // skip之后:7
        // skip之后:8
        // skip之后:9
        //skip之后:10

        Long collect = StudentEntity.createInitStudentList().stream()
                .map(StudentEntity::getAge)
                .collect(Collectors.summingLong(Long::valueOf));

        //直接转化为sum
        int studentAgeSum = StudentEntity.createInitStudentList().stream()
                .mapToInt(StudentEntity::getAge)
                .sum();
        //mapToInt 会从每个学生中提取年龄,并返回一个IntStream (而不是Stream),然后就可以调用IntStream中的sum方法,
        //对年龄求和了。如果流是空的,那么sum=0;IntStream还可以返回其他方法,例如:max,min,average等。

        //将原始流转化为一般流(每个int都会装箱为一个Integer),可以使用boxed
        Stream boxed = StudentEntity.createInitStudentList().stream().mapToInt(StudentEntity::getAge)
                .boxed();
        //返回的是stream,而不是intStream

        int maxValue = StudentEntity.createInitStudentList().stream()
                .mapToInt(StudentEntity::getAge)
                .max().orElse(1);
        logger.info("最大值:{}", maxValue);

    }

推荐一个讲解很全的博客:玩转Java8Stream(四、IntStream)

总结

       对于一些数字,可以用mapToInt 转化为数值流,完成数字的求和,最大最小,平均数,count 等;

       同时可以通过boxed把数值流转化为stream,然后完成一些stream 流的操作;

        取值范围,可以对有限的数字,做相应的处理。

你可能感兴趣的:(java)