Java8新特性之stream、map和reduce_zl_StepByStep的博客-程序员宝宝

技术标签: Java 面试  map和reduce  创建流  数值流  stream  java新特性  

    Java8新了stream API,需要注意的是Stream和I/O中的流是没有关系的,这个stream主要是要来处理集合数据的,可以将其看作一个高级迭代器。在Collection接口中新增了非抽象的stream方法来获取集合的流

     另外,Java8中新增了一个Optional类用于处理空指针异常,该类位于java.util包下,使用这个类可以更好的支持函数式编程,并且可以简化以前对null的判断。

目录

stream

map和reduce

Optional类


 

stream

下面定义一个Student类:

public class Student {

    private String name;
    private int score;

    public Student(){

    }

    public Student(String name, int score) {
        super();
        this.name = name;
        this.score = score;
    }

    //setter和getter省略

    @Override
    public String toString() {
        return "[姓名=" + name + ", 分数=" + score + "]";
    }

}

测试类:

public class StreamTest01 {
    public static void main(String[] args) {
        List<Student> stuList = new ArrayList<>(10);
        stuList.add(new Student("刘一", 85));
        stuList.add(new Student("陈二", 90));
        stuList.add(new Student("张三", 98));
        stuList.add(new Student("李四", 88));
        stuList.add(new Student("王五", 83));
        stuList.add(new Student("赵六", 95));
        stuList.add(new Student("孙七", 87));
        stuList.add(new Student("周八", 84));
        stuList.add(new Student("吴九", 100));
        stuList.add(new Student("郑十", 95));

        //需求:列出90分以上的学生姓名,并按照分数降序排序

        //以前的写法,代码较多,每个操作都需要遍历集合
        List<Student> result1 = new ArrayList<>(10);
        //遍历集合获取分数大于90以上的学生并存放到新的List中
        for(Student s : stuList){
            if(s.getScore() >= 90){
                result1.add(s);
            }
        }
        //对List进行降序排序
        result1.sort(new Comparator<Student>(){
            @Override
            public int compare(Student s1, Student s2) {
                //降序排序
                return Integer.compare(s2.getScore(), s1.getScore());
            }
        });
        System.out.println(result1);

        //使用stream的写法
        /*
         * 1.获取集合的stream对象
         * 2.使用filter方法完成过滤
         * 3.使用sort方法完成排序
         * 4.使用collect方法将处理好的stream对象转换为集合对象
         */
        result1 = stuList.stream()
                .filter(s -> s.getScore()>=90)
                //.sorted((s1,s2) -> Integer.compare(s2.getScore(), s1.getScore()))
                //使用Comparator中的comparing方法
                .sorted(Comparator.comparing(Student :: getScore).reversed())
                .collect(Collectors.toList());
        System.out.println(result1);
    }
}

streamæ°ææµç¨å¾1

    流的操作是内部迭代的,之前使用诸如for循环、迭代器属于外部迭代。不过在java8中内部迭代的性能还是略差一些,相信在后面的版本中会有所提升。注意:流只能使用一次,使用结束之后,这个流也就废掉了。

 

注:下面例子中都会用到上述测试类中的stuList,把这些数据放在InitData类中的getStudent方法里。

 

map和reduce

  • map用来归类,结果一般是一组数据,比如可以将list中的学生分数映射到一个新的stream中。
  • reduce用来计算值,结果是一个值,比如计算最高分。
public class StreamTest02 {

    public static void main(String[] args) {
        //初始化List数据同上
        List<Student> list = InitData.getStudent();
        //使用map方法获取list数据中的name
        List<String> names = list.stream().map(Student::getName).collect(Collectors.toList());
        System.out.println(names);

        //使用map方法获取list数据中的name的长度
        List<Integer> length = list.stream().map(Student::getName).map(String::length).collect(Collectors.toList());
        System.out.println(length);

        //将每人的分数-10
        List<Integer> score = list.stream().map(Student::getScore).map(i -> i - 10).collect(Collectors.toList());
        System.out.println(score);

        //计算学生总分
        Integer totalScore1 = list.stream().map(Student::getScore).reduce(0,(a,b) -> a + b);
        System.out.println(totalScore1);

        //计算学生总分,返回Optional类型的数据,改类型是java8中新增的,主要用来避免空指针异常
        Optional<Integer> totalScore2 = list.stream().map(Student::getScore).reduce((a,b) -> a + b);
        System.out.println(totalScore2.get());

        //计算最高分和最低分
        Optional<Integer> max = list.stream().map(Student::getScore).reduce(Integer::max);
        Optional<Integer> min = list.stream().map(Student::getScore).reduce(Integer::min);

        System.out.println(max.get());
        System.out.println(min.get());
    }
}

 

数值流

上面代码中

Optional<Integer> totalScore2 = list.stream()
                .map(Student::getScore)
                .reduce((a,b) -> a + b);

如果要是在Stream中有一个sum方法的话,可以修改为

Optional<Integer> totalScore2 = list.stream()
                .map(Student::getScore)
                .sum();

不过没有,但是在java8中新增了三个原始类型流(IntStream、DoubleStream、LongStream)来解决这个问题,

//数值流
public class StreamTest03 {
    public static void main(String[] args) {
        List<Student> list = InitData.getStudent();

        //将stream转换为IntStream
        int totalScore = list.stream().mapToInt(Student::getScore).sum();
        System.out.println(totalScore);

        //计算平均分
        OptionalDouble avgScore = list.stream().mapToInt(Student::getScore).average();
        System.out.println(avgScore.getAsDouble());

        //生成1~100之间的数字
        IntStream num = IntStream.rangeClosed(1, 100);

        //计算1~100之间的数字中偶数的个数
        long count = IntStream.rangeClosed(1, 100).filter(n -> n%2 == 0).count();
        System.out.println(count);
    }
}

 

创建流

除了上面的流之外,我们还可以自己创建流。下面代码中展示了三种创建流的方式:

//使用Stream.of创建流
    Stream<String> str =  Stream.of("i","love","this","game");
    str.map(String::toUpperCase).forEach(System.out::println);

    //使用数组创建流
    int[] num = {2,5,9,8,6};
    IntStream intStream = Arrays.stream(num);
    int sum = intStream.sum();//求和
    System.out.println(sum);

    //由函数生成流,创建无限流
    Stream.iterate(0, n -> n+2).limit(10).forEach(System.out::println);

 

Optional类

两个作用:(1)解决空指针异常  (2)支持函数式编程,所以使用它可以简化代码

例子:

public class TestOptional {
    public static void main(String[] args) {
        List<Student> studentList = InitData.getStudent();
        //计算分数在60分一下的分数总和
        Optional<Integer> score = studentList.stream()
                .map(Student :: getScore)
                .filter(s -> s<60)
                .reduce((a,b) -> a+b); //没有60分以下的,以前不加判断就会出现空指针异常
        System.out.println(score.orElse(0));   //0

        Map<Integer,String> map = new HashMap<>();
        map.put(20180001,"章子");
        map.put(20180002,"小米");
        map.put(20180003,"大黄");
        map.put(20180004,"靓妹");

        String name = Optional.ofNullable(map.get(20180005)).orElse("无");
        System.out.println(name);  //无
    }
}

 

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/zl_StepByStep/article/details/82729657

智能推荐

.NET深入解析LINQ框架(四:IQueryable、IQueryProvider接口详解)_weixin_33688840的博客-程序员宝宝

阅读目录:1.开篇介绍2.扩展Linq to Object (应用框架具有查询功能)2.1.通过添加IEnumerable&lt;T&gt;对象的扩展方法2.2.通过继承IEnumerable&lt;T&gt;接口2.3.详细的对象结构图3.实现IQueryable&lt;T&gt; 、IQueryProvider接口...

超好用的k8s中pod诊断工具:kubectl-debug_运维开发故事的博客-程序员宝宝_kubectl-debug

微信公众号:运维开发故事,作者:double冬背景容器技术的一个最佳实践是构建尽可能精简的容器镜像。但这一实践却会给排查问题带来麻烦:精简后的容器中普遍缺失常用的排障工具,部分容器里甚至没有 shell (比如 FROM scratch )。 在这种状况下,我们只能通过日志或者到宿主机上通过 docker-cli 或 nsenter 来排查问题,效率很低,在K8s环境部署应用后,经常遇到需要进入pod进行排错。除了查看pod logs和describe方式之外,传统的解决方式是在业务pod基础镜像中提前

Java代码操作SVN_w1764033735的博客-程序员宝宝

package com.leadbank.oprPlatform.util;import org.slf4j.Logger;import org.slf4j.LoggerFactory;import org.tmatesoft.svn.core.*;import org.tmatesoft.svn.core.internal.io.dav.DAVRepositoryFactory;import o

mysql乐观锁总结和实践:用version或者时间戳_拔苦与乐喵的博客-程序员宝宝

转载:http://chenzhou123520.iteye.com/blog/1863407原作者:chenzhou123520上一篇文章《MySQL悲观锁总结和实践》谈到了MySQL悲观锁,但是悲观锁并不是适用于任何场景,它也有它存在的一些不足,因为悲观锁大多数情况下依靠数据库的锁机制实现,以保证操作最大程度的独占性。如果加锁的时间过长,其他用户长时间无法访问,影响了程序的并发访问性,同时这样...

警惕Third Party Content***_weixin_33958585的博客-程序员宝宝

警惕Third Party Content***作者:SuperHei&quot;对于web应用程序,很多程序为了实现一些功能比如程序升级/提醒,还有广告什么的都直接在程序里使用了Third Party Content,那么当官方等站被黑时,基本使用你程序的用户都被xx了,这个以后也有可能和crsf一样成为一种vul呢?&quot;上面的文字引用于年前的一个blog:http://hi.baidu.com...

sql的行转列(PIVOT)与列转行(UNPIVOT)_一朵风中摇曳的水仙花的博客-程序员宝宝

 在做数据统计的时候,行转列,列转行是经常碰到的问题。case when方式太麻烦了,而且可扩展性不强,可以使用 PIVOT,UNPIVOT比较快速实现行转列,列转行,而且可扩展性强一、行转列1、测试数据准备 CREATE TABLE [StudentScores]( [UserName] NVARCHAR(20), --学生姓名 ...

随便推点

Material Design 控件(二)_weixin_30399821的博客-程序员宝宝

SnackbarSnackbar 与 Toast非常相像,但是Snackbar并不是用来取代Toast的。Toast用来提示用户发生了什么,而用户只能被动的接受,本不能做出任何提醒。Snackbar可以进行提示,同时也可以接受当用户点击时,去执行一些操作。用法:btn.setOnClickListener(new View.OnClickListener() { @O...

开发程序的步骤(自己开发程序的总结)_ufwt的博客-程序员宝宝

开发加单元测试 用单元测试跑代码覆盖率 如果不满意,就加没有运行到的代码的测试 用单元测试跑memory leak... 实际系统测试 

springboot使用JdbcTemplate操作mysql数据库_cristom的博客-程序员宝宝

新建工程采用idea的spring boot创建向导创建web工程demopom依赖&lt;dependency&gt; &lt;groupId&gt;mysql&lt;/groupId&gt; &lt;artifactId&gt;mysql-connector-java&lt;/artifactId&gt; &lt;/depe...

appcan请求腾讯地图,传参经纬度逆地址解析返回数据是null的问题_枫林晚风起的博客-程序员宝宝

1.请求方式安卓手机升级8.0以后,很不明白为什么不支持$.ajax和$zy_json的调用,只能用appcan.request.ajax,但是ios的话对于appacan.request.ajax的支持不是很好,最好判断一下系统,然后选择调用2.申请腾讯地图秘钥登陆腾讯地图开放平台,接入指引,申请秘钥,这个申请挺快的,但是记得要配置一下、把这个选中,不然在电脑调试没有权限的3...

监控io性能/free命令/ps命令/查看网络状况/linux下抓包_weixin_33725807的博客-程序员宝宝

监控io性能使用iostat命令查看磁盘使用情况[[email protected] ~]# iostat -x这里我们主要关注util这一列,util是个百分比显示的,如果这个值越大则表示你的硬盘越忙,这也会是你系统变慢的原因使用iotop命令查看那个进程使用磁盘大首先需要先安装这个命令[[email protected] ~]# yum install -y iotop[[email protected] ~]#...

All Mulberry bags are vibrant and, ultimately, fun._weixin_30929011的博客-程序员宝宝

Yes, the oversized designer Mulberry bag is still very much in---and not likely to go out of style anytime soon. In fact, following the oversized clutch trend of 2008 is a new oversized must-have: spr...

推荐文章

热门文章

相关标签