- Java 8 Stream API使用实践
- 一、前言
- 简介
- 环境
- 二、正文
- 流程
- 示例数据
- 创建流
- 过滤
- filter 过滤
- distinct 去重
- sorted 排序
- limit 限制
- skip 跳过
- 映射
- map
- flatMap
- 查找
- allMatch
- anyMatch
- noneMatch
- findFirst
- findAny
- 归纳计算
- count
- min-max
- sum
- avg
- summarizing
- joining
- 分组
- groupingBy 分组
- partitioningBy 分区
Java 8 API 添加了一个新的抽象称为流Stream。
Stream 可实现类似 SQL 查询数据的方式,对集合数据的进行一系列的筛选操作。
环境- 开发工具:IntelliJ IDEA
- JDK:1.8
二、正文 流程java stream api:https://docs.oracle.com/javase/8/docs/api/java/util/stream/Stream.html
runoob stream:https://www.runoob.com/java/java8-streams.html
colobu(smallnest):https://colobu.com/2016/03/02/Java-Stream/
segmentfault(宜信技术学院):https://segmentfault.com/a/1190000019574204
- 数据源 ==> 流 ==> 操作(过滤、分组、统计、排序等) ==> 结果数据
- 添加依赖
org.projectlombok lombok 1.18.22 provided com.alibaba fastjson 1.2.62
- 书籍信息
package com.example;
import lombok.Data;
@Data
public class Book {
private String title; // 书名
private String author; // 作者
private String publicationDate; // 出版时间(年份)
private String publisher; // 出版社
private double price; // 价格
private int suitability; // 是否套装 0=否,1=是
public Book() {}
public Book(String title, String author, String publicationDate
, String publisher, double price, int suitability) {
this.title = title;
this.author = author;
this.publicationDate = publicationDate;
this.publisher = publisher;
this.price = price;
this.suitability = suitability;
}
@Override
public String toString() {
return "Book{" +
"title='" + title + ''' +
", author='" + author + ''' +
", publicationDate='" + publicationDate + ''' +
", publisher='" + publisher + ''' +
", price=" + price +
", suitability=" + suitability +
'}';
}
}
- 测试数据
List创建流books = Arrays.asList( new Book("1分钟数学", "超模君,方运加", "2021", "北京大学出版社", 47.40, 0), new Book("1分钟数学", "超模君,方运加", "2021", "北京大学出版社", 47.40, 0), new Book("奇妙的粒子世界", "黄涛,曹俊", "2021", "北京大学出版社", 28.40, 0), new Book("科学的旅程(珍藏版)", "雷·斯潘根贝格", "2014", "北京大学出版社", 99.20, 0), new Book("冰心经典套装", "冰心", "2017", "浙江工商大学出版社", 55.30, 1), new Book("芥子园画谱套装全四卷", "王概", "2017", "北京联合出版有限公司", 74.30, 1), new Book("东野圭吾四大烧脑套装", "东野圭吾", "2020", "北京十月文艺出版社", 96.70, 1) );
| api | 说明 |
|---|---|
| stream() | 串行流 |
| parallelStream() | 并行流 |
- 场景说明:过滤大于 50 元以上的书籍
books = books.stream().filter(book -> book.getPrice() > 50).collect(Collectors.toList()); books.forEach(System.out::println);
- 结果
distinct 去重Book{title=‘科学的旅程(珍藏版)’, author=‘雷·斯潘根贝格’, publicationDate=‘2014’, publisher=‘北京大学出版社’, price=99.2, suitability=0}
Book{title=‘冰心经典套装’, author=‘冰心’, publicationDate=‘2017’, publisher=‘浙江工商大学出版社’, price=55.3, suitability=1}
Book{title=‘芥子园画谱套装全四卷’, author=‘王概’, publicationDate=‘2017’, publisher=‘北京联合出版有限公司’, price=74.3, suitability=1}
Book{title=‘东野圭吾四大烧脑套装’, author=‘东野圭吾’, publicationDate=‘2020’, publisher=‘北京十月文艺出版社’, price=96.7, suitability=1}
- 场景说明:去除相同的书籍数据
books = books.stream().distinct().collect(Collectors.toList()); books.forEach(System.out::println);
- 结果
sorted 排序Book{title=‘1分钟数学’, author=‘超模君,方运加’, publicationDate=‘2021’, publisher=‘北京大学出版社’, price=47.4, suitability=0}
Book{title=‘奇妙的粒子世界’, author=‘黄涛,曹俊’, publicationDate=‘2021’, publisher=‘北京大学出版社’, price=28.4, suitability=0}
Book{title=‘科学的旅程(珍藏版)’, author=‘雷·斯潘根贝格’, publicationDate=‘2014’, publisher=‘北京大学出版社’, price=99.2, suitability=0}
Book{title=‘冰心经典套装’, author=‘冰心’, publicationDate=‘2017’, publisher=‘浙江工商大学出版社’, price=55.3, suitability=1}
Book{title=‘芥子园画谱套装全四卷’, author=‘王概’, publicationDate=‘2017’, publisher=‘北京联合出版有限公司’, price=74.3, suitability=1}
Book{title=‘东野圭吾四大烧脑套装’, author=‘东野圭吾’, publicationDate=‘2020’, publisher=‘北京十月文艺出版社’, price=96.7, suitability=1}
- 场景说明:根据价格进行排序(顺序、倒序)
// 排序
System.out.println("--顺序========");
books = books.stream().sorted(Comparator.comparingDouble(Book::getPrice)).collect(Collectors.toList());
books.forEach(System.out::println);
System.out.println("--倒序========");
books = books.stream().sorted(Comparator.comparingDouble(Book::getPrice).reversed()).collect(Collectors.toList());
books.forEach(System.out::println);
- 结果
limit 限制**–顺序========**
Book{title=‘奇妙的粒子世界’, author=‘黄涛,曹俊’, publicationDate=‘2021’, publisher=‘北京大学出版社’, price=28.4, suitability=0}
Book{title=‘1分钟数学’, author=‘超模君,方运加’, publicationDate=‘2021’, publisher=‘北京大学出版社’, price=47.4, suitability=0}
Book{title=‘1分钟数学’, author=‘超模君,方运加’, publicationDate=‘2021’, publisher=‘北京大学出版社’, price=47.4, suitability=0}
Book{title=‘冰心经典套装’, author=‘冰心’, publicationDate=‘2017’, publisher=‘浙江工商大学出版社’, price=55.3, suitability=1}
Book{title=‘芥子园画谱套装全四卷’, author=‘王概’, publicationDate=‘2017’, publisher=‘北京联合出版有限公司’, price=74.3, suitability=1}
Book{title=‘东野圭吾四大烧脑套装’, author=‘东野圭吾’, publicationDate=‘2020’, publisher=‘北京十月文艺出版社’, price=96.7, suitability=1}
Book{title=‘科学的旅程(珍藏版)’, author=‘雷·斯潘根贝格’, publicationDate=‘2014’, publisher=‘北京大学出版社’, price=99.2, suitability=0}
**–倒序========**
Book{title=‘科学的旅程(珍藏版)’, author=‘雷·斯潘根贝格’, publicationDate=‘2014’, publisher=‘北京大学出版社’, price=99.2, suitability=0}
Book{title=‘东野圭吾四大烧脑套装’, author=‘东野圭吾’, publicationDate=‘2020’, publisher=‘北京十月文艺出版社’, price=96.7, suitability=1}
Book{title=‘芥子园画谱套装全四卷’, author=‘王概’, publicationDate=‘2017’, publisher=‘北京联合出版有限公司’, price=74.3, suitability=1}
Book{title=‘冰心经典套装’, author=‘冰心’, publicationDate=‘2017’, publisher=‘浙江工商大学出版社’, price=55.3, suitability=1}
Book{title=‘1分钟数学’, author=‘超模君,方运加’, publicationDate=‘2021’, publisher=‘北京大学出版社’, price=47.4, suitability=0}
Book{title=‘1分钟数学’, author=‘超模君,方运加’, publicationDate=‘2021’, publisher=‘北京大学出版社’, price=47.4, suitability=0}
Book{title=‘奇妙的粒子世界’, author=‘黄涛,曹俊’, publicationDate=‘2021’, publisher=‘北京大学出版社’, price=28.4, suitability=0}
- 场景说明:返回前 3 条数据
books = books.stream().limit(3).collect(Collectors.toList()); books.forEach(System.out::println);
- 结果
skip 跳过Book{title=‘1分钟数学’, author=‘超模君,方运加’, publicationDate=‘2021’, publisher=‘北京大学出版社’, price=47.4, suitability=0}
Book{title=‘1分钟数学’, author=‘超模君,方运加’, publicationDate=‘2021’, publisher=‘北京大学出版社’, price=47.4, suitability=0}
Book{title=‘奇妙的粒子世界’, author=‘黄涛,曹俊’, publicationDate=‘2021’, publisher=‘北京大学出版社’, price=28.4, suitability=0}
- 场景说明:跳过前 5 条数据
books = books.stream().skip(5).collect(Collectors.toList()); books.forEach(System.out::println);
- 结果
映射 mapBook{title=‘芥子园画谱套装全四卷’, author=‘王概’, publicationDate=‘2017’, publisher=‘北京联合出版有限公司’, price=74.3, suitability=1}
Book{title=‘东野圭吾四大烧脑套装’, author=‘东野圭吾’, publicationDate=‘2020’, publisher=‘北京十月文艺出版社’, price=96.7, suitability=1}
- 场景说明:获取书名集合
Listtitles = books.stream().map(Book::getTitle).collect(Collectors.toList()); titles.forEach(System.out::println);
- 结果
flatMap1分钟数学
1分钟数学
奇妙的粒子世界
科学的旅程(珍藏版)
冰心经典套装
芥子园画谱套装全四卷
东野圭吾四大烧脑套装
- 场景说明:获取作者名字列表,并将多个作者的名字进行拆分(逗号分隔),最终形成列表数据
Listauthors = books.stream().map(Book::getAuthor) .map(author -> author.split(",")).flatMap(Arrays::stream).collect(Collectors.toList()); authors.forEach(System.out::println);
- 结果
查找 allMatch超模君
方运加
超模君
方运加
黄涛
曹俊
雷·斯潘根贝格
冰心
王概
东野圭吾
- 场景说明:所有书籍中是否全部书籍的价格都大于 20 元
boolean isPrice = books.stream().allMatch(book -> book.getPrice() > 20); System.out.println(isPrice);
- 结果
anyMatchtrue
说明:全部书籍的价格大于 20 元
- 场景说明:所有书籍中是否有套装书籍
boolean isSuitability = books.stream().anyMatch(book -> book.getSuitability() == 1); System.out.println(isSuitability);
- 结果
noneMatchtrue
说明:有套装书籍
- 场景说明:所有书籍中是否有套装书籍
boolean isSuitability = books.stream().noneMatch(book -> book.getSuitability() == 1); System.out.println(isSuitability);
- 结果
findFirstfalse
说明:有套装书籍
- 场景说明:获取第一本书籍
Optionalbook = books.stream().findFirst(); System.out.println( book.get() );
- 结果
findAnyBook{title=‘1分钟数学’, author=‘超模君,方运加’, publicationDate=‘2021’, publisher=‘北京大学出版社’, price=47.4, suitability=0}
- 场景说明:获取随机一本书籍
Optionalbook = books.parallelStream().findAny(); System.out.println( book.get() );
- 结果
归纳计算 countBook{title=‘冰心经典套装’, author=‘冰心’, publicationDate=‘2017’, publisher=‘浙江工商大学出版社’, price=55.3, suitability=1}
- 场景说明:计算所有书籍的总数
long count = books.stream().count(); System.out.println(count);
- 结果
min-max7
- 场景说明:计算所有书籍中,最小价格的书籍和最大价格的书籍
Optionalbook = books.stream().collect(Collectors.minBy(Comparator.comparing(Book::getPrice))); System.out.println( "min=" + book.get().getPrice() ); book = books.stream().collect(Collectors.maxBy(Comparator.comparing(Book::getPrice))); System.out.println( "max=" + book.get().getPrice() );
- 结果
summin=28.4
max=99.2
- 场景说明:计算所有书籍的价格总和
Double sumPrice = books.stream().collect(Collectors.summingDouble(Book::getPrice)); System.out.println(sumPrice);
- 结果
448.7
- 假设:价格的数据类型为:BigDecimal
BigDecimal sumPrice = books.stream().map(Book::getPrice).reduce(BigDecimal.ZERO,BigDecimal::add); System.out.println(sumPrice);avg
场景说明:计算所有书籍的平均价格
Double avgPrice = books.stream().collect(Collectors.averagingDouble(Book::getPrice)); System.out.println(avgPrice);
- 结果
summarizing64.1
场景说明:同时计算出所有书籍价格的个数、总和、最小值和最大值
DoubleSummaryStatistics statistics = books.stream().collect(Collectors.summarizingDouble(Book::getPrice)); System.out.println(statistics);
- 结果
joiningDoubleSummaryStatistics{count=7, sum=448.700000, min=28.400000, average=64.100000, max=99.200000}
- 场景说明:将书名拼接为字符串,使用逗号进行分隔
String titleStr = books.stream().map(Book::getTitle).collect(Collectors.joining(","));
System.out.println(titleStr);
- 结果
分组 groupingBy 分组1分钟数学,1分钟数学,奇妙的粒子世界,科学的旅程(珍藏版),冰心经典套装,芥子园画谱套装全四卷,东野圭吾四大烧脑套装
- 场景 1 说明:根据出版社进行分组
Map> map = books.stream().collect(Collectors.groupingBy(Book::getPublisher)); System.out.println(JSON.toJSONString(map));
- 结果(JSON 字符串)
{“北京十月文艺出版社”:[{“author”:“东野圭吾”,“price”:96.7,“publicationDate”:“2020”,“publisher”:“北京十月文艺出版社”,“suitability”:1,“title”:“东野圭吾四大烧脑套装”}],“北京大学出版社”:[{“author”:“超模君,方运加”,“price”:47.4,“publicationDate”:“2021”,“publisher”:“北京大学出版社”,“suitability”:0,“title”:“1分钟数学”},{“author”:“超模君,方运加”,“price”:47.4,“publicationDate”:“2021”,“publisher”:“北京大学出版社”,“suitability”:0,“title”:“1分钟数学”},{“author”:“黄涛,曹俊”,“price”:28.4,“publicationDate”:“2021”,“publisher”:“北京大学出版社”,“suitability”:0,“title”:“奇妙的粒子世界”},{“author”:“雷·斯潘根贝格”,“price”:99.2,“publicationDate”:“2014”,“publisher”:“北京大学出版社”,“suitability”:0,“title”:“科学的旅程(珍藏版)”}],“北京联合出版有限公司”:[{“author”:“王概”,“price”:74.3,“publicationDate”:“2017”,“publisher”:“北京联合出版有限公司”,“suitability”:1,“title”:“芥子园画谱套装全四卷”}],“浙江工商大学出版社”:[{“author”:“冰心”,“price”:55.3,“publicationDate”:“2017”,“publisher”:“浙江工商大学出版社”,“suitability”:1,“title”:“冰心经典套装”}]}
- 场景 2 说明:根据出版社进行分组后,再根据是否套装进行分组(二级分组)
Map>> map = books.stream() .collect(Collectors.groupingBy(Book::getPublisher, Collectors.groupingBy(Book::getSuitability))); System.out.println(JSON.toJSONString(map));
- 结果(JSON 字符串)
{“北京十月文艺出版社”:{1:[{“author”:“东野圭吾”,“price”:96.7,“publicationDate”:“2020”,“publisher”:“北京十月文艺出版社”,“suitability”:1,“title”:“东野圭吾四大烧脑套装”}]},“北京大学出版社”:{0:[{“author”:“超模君,方运加”,“price”:47.4,“publicationDate”:“2021”,“publisher”:“北京大学出版社”,“suitability”:0,“title”:“1分钟数学”},{“author”:“超模君,方运加”,“price”:47.4,“publicationDate”:“2021”,“publisher”:“北京大学出版社”,“suitability”:0,“title”:“1分钟数学”},{“author”:“黄涛,曹俊”,“price”:28.4,“publicationDate”:“2021”,“publisher”:“北京大学出版社”,“suitability”:0,“title”:“奇妙的粒子世界”},{“author”:“雷·斯潘根贝格”,“price”:99.2,“publicationDate”:“2014”,“publisher”:“北京大学出版社”,“suitability”:0,“title”:“科学的旅程(珍藏版)”}]},“北京联合出版有限公司”:{1:[{“author”:“王概”,“price”:74.3,“publicationDate”:“2017”,“publisher”:“北京联合出版有限公司”,“suitability”:1,“title”:“芥子园画谱套装全四卷”}]},“浙江工商大学出版社”:{1:[{“author”:“冰心”,“price”:55.3,“publicationDate”:“2017”,“publisher”:“浙江工商大学出版社”,“suitability”:1,“title”:“冰心经典套装”}]}}
场景 3 说明:根据出版社进行分组后,统计书籍的数量
Mapmap = books.stream().collect(Collectors.groupingBy(Book::getPublisher, Collectors.counting())); System.out.println(JSON.toJSONString(map));
- 结果(JSON 字符串)
partitioningBy 分区{“北京十月文艺出版社”:1,“北京大学出版社”:4,“北京联合出版有限公司”:1,“浙江工商大学出版社”:1}
- 场景说明:根据价格进行分区,价格是否大于50元
Map> map = books.stream().collect(Collectors.partitioningBy(book -> book.getPrice() > 50)); System.out.println(JSON.toJSONString(map));
- 结果(JSON 字符串)
{false:[{“author”:“超模君,方运加”,“price”:47.4,“publicationDate”:“2021”,“publisher”:“北京大学出版社”,“suitability”:0,“title”:“1分钟数学”},{“author”:“超模君,方运加”,“price”:47.4,“publicationDate”:“2021”,“publisher”:“北京大学出版社”,“suitability”:0,“title”:“1分钟数学”},{“author”:“黄涛,曹俊”,“price”:28.4,“publicationDate”:“2021”,“publisher”:“北京大学出版社”,“suitability”:0,“title”:“奇妙的粒子世界”}],true:[{“author”:“雷·斯潘根贝格”,“price”:99.2,“publicationDate”:“2014”,“publisher”:“北京大学出版社”,“suitability”:0,“title”:“科学的旅程(珍藏版)”},{“author”:“冰心”,“price”:55.3,“publicationDate”:“2017”,“publisher”:“浙江工商大学出版社”,“suitability”:1,“title”:“冰心经典套装”},{“author”:“王概”,“price”:74.3,“publicationDate”:“2017”,“publisher”:“北京联合出版有限公司”,“suitability”:1,“title”:“芥子园画谱套装全四卷”},{“author”:“东野圭吾”,“price”:96.7,“publicationDate”:“2020”,“publisher”:“北京十月文艺出版社”,“suitability”:1,“title”:“东野圭吾四大烧脑套装”}]}



