Java Stream基本用法

介绍

Java Stream是Java 8中引入的一个新的抽象概念,它允许以声明式的方式处理数据集合。Stream将要处理的元素集合视为一种流,在流的过程中,可以利用Stream API对元素进行各种操作,如筛选、排序、聚合等。Stream操作可以分为中间操作和终端操作,中间操作每次返回一个新的流,可以有多个,而终端操作则产生一个结果或一个新的集合

创建list集合数据

List<Stu> stuData(){
    List<Stu> stuList = new ArrayList<>();
    stuList.add(new Stu(1,"张安",20));
    stuList.add(new Stu(2,"李四",38));
    stuList.add(new Stu(3,"王五",19));
    stuList.add(new Stu(4,"赵六",76));
    return stuList;
}
//科目数据
List<Course> courseList(){
    List<Course> courseList = new ArrayList<>();
    courseList.add(new Course(1,"语文"));
    courseList.add(new Course(2,"数学"));
    courseList.add(new Course(3,"英语"));
    return courseList;
}


//成绩数据
List<Score> scoreData(){
    List<Score> scoreList = new ArrayList<>();
    scoreList.add(new Score(1,1,80));
    scoreList.add(new Score(1,2,90));
    scoreList.add(new Score(1,3,70));
    scoreList.add(new Score(2,1,79));
    scoreList.add(new Score(2,2,98));
    scoreList.add(new Score(2,3,78));
    scoreList.add(new Score(3,1,98));
    scoreList.add(new Score(3,2,76));
    scoreList.add(new Score(3,3,88));
    scoreList.add(new Score(4,1,99));
    return scoreList;
}

使用stream条件输出

/**
 * stream条件输出
 * 判断条件: 张三
 * */
@Test
void streamPrintOut(){
    List<Stu> list = stuData();
    list.stream()
            .filter(stu -> "张安".equals(stu.getStuName()))
            .forEach(System.out::println);
            //Stu(stuId=1, stuName=张安, stuAge=20)
}

统计

/**
 * 统计
 * 条件:年龄大于20岁
 * */
@Test
void ageGtCount(){
    List<Stu> list = stuData();
    long count = list.stream().filter(stu -> stu.getStuAge()>20).count();
    System.out.println(count);// 2
}

排序

正序

/**
 * 年龄排序
 * 正序
 * */
@Test
void ageSort(){
    List<Stu> list = stuData();
    list.stream()
            .sorted(Comparator.comparing(Stu::getStuAge))
            .forEach(System.out::println);
    //Stu(stuId=3, stuName=王五, stuAge=19)
    //Stu(stuId=1, stuName=张安, stuAge=20)
    //Stu(stuId=2, stuName=李四, stuAge=38)
    //Stu(stuId=4, stuName=赵六, stuAge=76)
}

倒序

/**
 * 年龄排序
 * 倒序
 * */
@Test
void ageSort(){
    List<Stu> list = stuData();
    list.stream()
            .sorted(Comparator.comparing(Stu::getStuAge).reversed())
            .forEach(System.out::println);
    //Stu(stuId=4, stuName=赵六, stuAge=76)
    //Stu(stuId=2, stuName=李四, stuAge=38)
    //Stu(stuId=1, stuName=张安, stuAge=20)
    //Stu(stuId=3, stuName=王五, stuAge=19)
}

去重

/**
 * 名字去重
 * */
@Test
void distinct(){
    List<Stu> list = stuData();
    list.add(new Stu(5,"张三",23));
    list.add(new Stu(6,"赵六",45));
    list.add(new Stu(7,"王五",43));
    list.stream().map(Stu::getStuName).distinct().forEach(System.out::println);
    //张安
    //李四
    //王五
    //赵六
    //张三
}

map

/**
 * map
 * 年龄相加
 * */
@Test
void map(){
    List<Stu> list = stuData();
    list.stream()
            .map(stu -> stu.getStuAge() + stu.getStuAge())
            .forEach(System.out::println);
    //40
    //76
    //38
    //152
}

summaryStatistics

/**
 * 函数统计
 * */
@Test
void function(){
    List<Stu> list = stuData();
    IntSummaryStatistics state = list.stream()
            .mapToInt(Stu::getStuAge)
            .summaryStatistics();
    System.out.println("最大年龄:"+state.getMax());//最大年龄:76
    System.out.println("最小年龄:"+state.getMin());//最小年龄:19
    System.out.println("总年龄:"+state.getSum());//总年龄:153
    System.out.println("平均年龄:"+state.getAverage());//平均年龄:38.25
    System.out.println("数量:"+state.getCount());//数量:4
}

分组

/**
 * 分组
 * */
@Test
void group(){
    List<Stu> list = stuData();
    list.add(new Stu(5,"张三",23));
    list.add(new Stu(6,"赵六",45));
    list.add(new Stu(7,"王五",43));
    Map<String, List<Stu>> collect = list.stream().collect(Collectors.groupingBy(Stu::getStuName));
    System.out.println(collect);
    //{
    //  李四=[Stu(stuId=2, stuName=李四, stuAge=38)], 
    //  张三=[Stu(stuId=5, stuName=张三, stuAge=23)], 
    //  张安=[Stu(stuId=1, stuName=张安, stuAge=20)], 
    //  王五=[Stu(stuId=3, stuName=王五, stuAge=19), Stu(stuId=7, stuName=王五, stuAge=43)], 
    //  赵六=[Stu(stuId=4, stuName=赵六, stuAge=76), Stu(stuId=6, stuName=赵六, stuAge=45)]
    // }
}

join联查

/**
 * stream两表联查
 * */
@Test
void join(){
    List<Score> scoreList = scoreData();
    List<StuInfo> infoList = scoreList.stream().map(score -> {
        List<Stu> stuList = stuData();//获取学生表的数据
        Stu stu = stuList.stream()
                .filter(stus -> stus.getStuId().equals(score.getStuId()))//根据score表中的stuId查询
                .distinct().findFirst().get();//获取单个对象
        StuInfo stuInfo = new StuInfo();//中间表
        BeanUtils.copyProperties(stu, stuInfo);//拷贝
        stuInfo.setScore(score.getScore());
        stuInfo.setScoreId(score.getScore());
        return stuInfo;
    }).collect(Collectors.toList());
    infoList.forEach(System.out::println);
    //StuInfo(stuId=1, stuName=张安, scoreId=80, score=80)
    //StuInfo(stuId=1, stuName=张安, scoreId=90, score=90)
    //StuInfo(stuId=1, stuName=张安, scoreId=70, score=70)
    //StuInfo(stuId=2, stuName=李四, scoreId=79, score=79)
    //StuInfo(stuId=2, stuName=李四, scoreId=98, score=98)
    //StuInfo(stuId=2, stuName=李四, scoreId=78, score=78)
    //StuInfo(stuId=3, stuName=王五, scoreId=98, score=98)
    //StuInfo(stuId=3, stuName=王五, scoreId=76, score=76)
    //StuInfo(stuId=3, stuName=王五, scoreId=88, score=88)
    //StuInfo(stuId=4, stuName=赵六, scoreId=99, score=99)
}

多表联查

/**
 * stream三表联查
 * */
@Test
void join(){
    List<Score> scoreList = scoreData();
    List<StuInfo> infoList = scoreList.stream().map(score -> {
        Stu stu = stuData().stream()
                .filter(stus -> stus.getStuId().equals(score.getStuId()))//根据score表中的stuId查询
                .distinct()//去重
                .findFirst().get();//获取单个对象
        StuInfo stuInfo = new StuInfo();//中间表
        BeanUtils.copyProperties(stu, stuInfo);//拷贝
        stuInfo.setScore(score.getScore());
        stuInfo.setScoreId(score.getScore());
        Course courses = courseList().stream()
                .filter(course -> course.getCourseId().equals(score.getCourseId()))//根据score表中courseId查询
                .distinct()
                .findFirst().get();
        stuInfo.setCourseName(courses.getCourseName());
        return stuInfo;
    }).collect(Collectors.toList());
    infoList.forEach(System.out::println);
}

输出

stream组合查询

计算各个学生总成绩

/**
 * 学生总成绩
 * */
@Test
void sumSort(){
    Map<Integer, Integer> averageScore = scoreData().stream()
            .collect(Collectors.groupingBy(
                    Score::getStuId,
                    Collectors.summingInt(Score::getScore)));
    System.out.println(averageScore);//{1=240, 2=255, 3=262, 4=99}
    //根学生信息连接
    List<StuInfo> infoList = averageScore.entrySet().stream().map(entry -> {
        Integer stuId = entry.getKey();//学生id
        Integer sum = entry.getValue();//总成绩
        //获取学生信息
        Stu stuData = stuData().stream().filter(stu -> stu.getStuId().equals(stuId)).findFirst().get();
        StuInfo stuInfo = new StuInfo();
        stuInfo.setSum(sum);
        stuInfo.setStuName(stuData.getStuName());
        stuInfo.setStuId(stuData.getStuId());
        return stuInfo;
    }).collect(Collectors.toList());
    infoList.forEach(System.out::println);
}

平均分

/**
 * 学生平均分
 * */
@Test
void average(){
    Map<Integer, Double> average = scoreData().stream()
            .collect(Collectors.groupingBy(
                    Score::getStuId,
                    Collectors.averagingDouble(Score::getScore)));
    System.out.println(average);//{1=80.0, 2=85.0, 3=87.33333333333333, 4=99.0}
    List<StuInfo> infoList = average.entrySet().stream().map(entry -> {
        Integer stuId = entry.getKey();//学生id
        Double avg = entry.getValue();//平均分
        Stu stuData = stuData().stream().filter(stu -> stu.getStuId().equals(stuId)).findFirst().get();
        StuInfo stuInfo = new StuInfo();
        stuInfo.setAvg(avg);
        stuInfo.setStuName(stuData.getStuName());
        stuInfo.setStuId(stuData.getStuId());
        return stuInfo;
    }).collect(Collectors.toList());
    infoList.forEach(System.out::println);
}

平均分+倒排序

/**
 * 学生平均分
 * */
@Test
void average(){
    Map<Integer, Double> average = scoreData().stream()
            .collect(Collectors.groupingBy(
                    Score::getStuId,
                    Collectors.averagingDouble(Score::getScore)));
    System.out.println(average);//{1=80.0, 2=85.0, 3=87.33333333333333, 4=99.0}
    List<StuInfo> infoList = average.entrySet().stream().map(entry -> {
        Integer stuId = entry.getKey();//学生id
        Double avg = entry.getValue();//平均分
        Stu stuData = stuData().stream().filter(stu -> stu.getStuId().equals(stuId)).findFirst().get();
        StuInfo stuInfo = new StuInfo();
        stuInfo.setAvg(avg);
        stuInfo.setStuName(stuData.getStuName());
        stuInfo.setStuId(stuData.getStuId());
        return stuInfo;
    }).sorted(Comparator.comparing(StuInfo::getAvg).reversed()).collect(Collectors.toList());
    infoList.forEach(System.out::println);
}

概率

/**
 * 学生考试成绩是否及格的占比,按照90分为标准
 * */
@Test
void pass(){
    int total = scoreData().size();//总参加考试次数
    //成绩大于90分
    long passCount = scoreData().stream().filter(score -> score.getScore() >= 90).count();
    //未及格人数
    long failCount = total - passCount;
    double pass =  (double) passCount / total * 100;
    double fail =  (double) failCount / total * 100;
    System.out.println("及格率:"+pass+"%");//及格率:40.0%
    System.out.println("不及格率:"+fail+"%");//不及格率:60.0%
}

分组统计

/**
 * 统计每门课程的学生选修人数
 * */
@Test
void countCourse(){
    //统计选修课数量
    Map<Integer, Long> collect = scoreData().stream().collect(Collectors.groupingBy(Score::getCourseId, Collectors.counting()));
    System.out.println(collect);//{1=4, 2=3, 3=3}
    List<CourseInfo> courseInfos = collect.entrySet().stream().map(entry -> {
        Integer courseId = entry.getKey();//科目id
        Long count = entry.getValue();//选修数量
        Course courseData = courseList().stream().filter(course -> course.getCourseId().equals(courseId)).findFirst().get();
        CourseInfo courseInfo = new CourseInfo();
        courseInfo.setCount(count);
        courseInfo.setCourseName(courseData.getCourseName());
        return courseInfo;
    }).collect(Collectors.toList());
    courseInfos.forEach(System.out::println);
}

计算金额

/**
 * 初始化用户数据
 * */
public List<User> initUser(){
    List<User> users = new ArrayList<>();
    users.add(new User(1,"张三"));
    users.add(new User(2,"李四"));
    users.add(new User(3,"王五"));
    return users;
}


/**
 * 初始化银行卡数据
 * */
public List<Bank> initBank(){
    List<Bank> banks = new ArrayList<>();
    banks.add(new Bank(1,BigDecimal.valueOf(3000),1));
    banks.add(new Bank(2,BigDecimal.valueOf(8000),1));
    banks.add(new Bank(3,BigDecimal.valueOf(12000),3));
    banks.add(new Bank(4,BigDecimal.valueOf(93000),3));
    banks.add(new Bank(5,BigDecimal.valueOf(53000),2));
    return banks;
}


/**
 * 计算该银行总金额
 * */
@Test
public void totalMoney(){
    BigDecimal reduce = initBank().stream().map(Bank::getMoney).reduce(BigDecimal.ZERO, BigDecimal::add);
    System.out.println(reduce);//169000
}


/**
 * 计算每个用户的总存款
 * */
@Test
public void deposit(){
    Map<Integer, BigDecimal> banks = initBank().stream()
            .collect(Collectors.toMap(
                    Bank::getUserId,
                    bank -> BigDecimal.ONE.multiply(bank.getMoney()),
                    BigDecimal::add));
    System.out.println(banks);//{1=11000, 2=53000, 3=105000}
    List<UserInfo> infoList = banks.entrySet().stream()
            .map(entry -> {
                Integer userId = entry.getKey();//用户id
                BigDecimal amount = entry.getValue();//用户总金额
                User userData = initUser().stream().filter(user -> user.getUserId().equals(userId))
                        .findFirst().get();
                UserInfo userInfo = new UserInfo();
                userInfo.setAmount(amount);
                userInfo.setUsername(userData.getUserName());
                return userInfo;
            }).collect(Collectors.toList());
    infoList.forEach(System.out::println);
}

总结 

Java Stream流,在java8后,我们可以会经常使用,提高了我们代码的美观,以及提高性能的效率,完美的将之前几十行上百行的操作或计算代码,用简单几行完成,同样,他可以集合mybatis-plus来完成许多sql查询,以及多表联查,我之前发过一篇mybatis-plus-join的文章,里面详细的描述了mybatis-plus的联查方式,但是我们在面对大量数据时,使用join连查还是会导致性能的下降,所以可以通过stream流来提升,过段时间,我还会出一期stream流+mybatis-plus联查。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值