介绍
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联查。
标签:Java,Stream,stream,List,用法,Stu,add,new,stuId From: https://blog.csdn.net/yxhsk8/article/details/142903517