JDK 1.8新特性 Stream流
一、Stream流介绍
从支持数据处理操作的源生成的元素序列。
-----《Java 8 实战》
流的特点在于支持函数式编程、提供管道运算能力、提供并行计算能力及提供大量的操作。
二、Stream流的操作步骤
- 创建Stream流 从一个数据源,如集合、数组中获取流。
- 中间操作 一个操作的中间链,对数据源的数据进行操作
- 终止操作 一个终止操作,执行中间操作链,并产生结果。
三、获得Stream流
获取一个流非常简单,有以下几种常见的方式:
- 通过Collection对象的stream()或者parallelStream()
List<Integer> list = Lists.newArrayList();
//串行 单线程
list.stream();
//并行 多线程
list.parallelStream();
- Stream接口的静态方法of可以获取数组对应的流。
Stream.of(1, 2, 3, 4, 5, 6);
- Arrays的静态方法stream也可以获取流
int[] numbers = {1, 2, 3, 4, 5};
IntStream stream = Arrays.stream(numbers);
stream.forEach(System.out::println);
- 通过文件流获取
四、Stream常见操作
Sku对象
@Getter
@AllArgsConstructor
public class Sku {
/**
* sku编号
*/
private Integer skuId;
/**
* 商品名称
*/
private String skuName;
/**
* 商品价格(仅测试使用Double类型)
*/
private Double skuPrice;
/**
* 购买个数
*/
private Integer totalNum;
/**
* 总价
*/
private Double totalPrice;
/**
* 商品分类
*/
private Enum skuCategory;
}
CartService,购物车服务类,用于将选购的sku放入购物车。
public class CartService {
// 加入到购物车中的商品信息
private static List<Sku> cartSkuList =
new ArrayList<Sku>(){
{
add(new Sku(654032, "无人机",
4999.00, 1,
4999.00, SkuCategoryEnum.ELECTRONICS));
add(new Sku(642934, "VR一体机",
2299.00, 1,
2299.00, SkuCategoryEnum.ELECTRONICS));
add(new Sku(645321, "纯色衬衫",
409.00, 3,
1227.00, SkuCategoryEnum.CLOTHING));
add(new Sku(654327, "牛仔裤",
528.00, 1,
528.00, SkuCategoryEnum.CLOTHING));
add(new Sku(675489, "跑步机",
2699.00, 1,
2699.00, SkuCategoryEnum.SPORTS));
add(new Sku(644564, "Java编程思想",
79.80, 1,
79.80, SkuCategoryEnum.BOOKS));
add(new Sku(678678, "Java核心技术",
149.00, 1,
149.00, SkuCategoryEnum.BOOKS));
add(new Sku(697894, "算法",
78.20, 1,
78.20, SkuCategoryEnum.BOOKS));
add(new Sku(696968, "TensorFlow进阶指南",
85.10, 1,
85.10, SkuCategoryEnum.BOOKS));
}
};
/**
* 获取商品信息列表
* @return
*/
public static List<Sku> getCartSkuList() {
return cartSkuList;
}
}
商品分类Enum类型
public enum SkuCategoryEnum {
CLOTHING(10, "服装类"),
ELECTRONICS(20, "数码类"),
SPORTS(30, "运动类"),
BOOKS(40, "图书类");
// 商品类型的编号
private Integer code;
// 商品类型的名称
private String name;
/**
* 构造函数
* @param code
* @param name
*/
SkuCategoryEnum(Integer code, String name) {
this.code = code;
this.name = name;
}
}
采用JUnit4进行单元测试,所有单元测试方法前执行初始化方法
List<Sku> list;
@Before
public void init(){
list = CartService.getCartSkuList();
}
4.1 filter
过滤掉不符合断言判断的数据记录
list.stream().filter(sku -> SkuCategoryEnum.BOOKS.equals(sku.getSkuCategory())).forEach(
item ->{
System.out.println(JSON.toJSONString(item,true));
}
);
{
"skuCategory":"BOOKS",
"skuId":644564,
"skuName":"Java编程思想",
"skuPrice":79.8,
"totalNum":1,
"totalPrice":79.8
}
{
"skuCategory":"BOOKS",
"skuId":678678,
"skuName":"Java核心技术",
"skuPrice":149.0,
"totalNum":1,
"totalPrice":149.0
}
{
"skuCategory":"BOOKS",
"skuId":697894,
"skuName":"算法",
"skuPrice":78.2,
"totalNum":1,
"totalPrice":78.2
}
{
"skuCategory":"BOOKS",
"skuId":696968,
"skuName":"TensorFlow进阶指南",
"skuPrice":85.1,
"totalNum":1,
"totalPrice":85.1
}
4.2 map
将一个元素转换为另一个元素
list.stream().map(sku -> sku.getSkuName()).forEach(
item -> System.out.println(JSON.toJSONString(item,true))
"无人机"
"VR一体机"
"纯色衬衫"
"牛仔裤"
"跑步机"
"Java编程思想"
"Java核心技术"
"算法"
"TensorFlow进阶指南"
4.3 flatMap
将一个流转换为另一个流
list.stream()
.flatMap(sku-> Arrays.stream(sku.getSkuName().split(""))).forEach(
item -> System.out.println(JSON.toJSONString(item,true))
);
"无"
"人"
"机"
"V"
"R"
"一"
"体"
"机"
"纯"
"色"
"衬"
"衫"
"牛"
"仔"
"裤"
"跑"
"步"
"机"
"J"
"a"
"v"
"a"
"编"
"程"
"思"
"想"
"J"
"a"
"v"
"a"
"核"
"心"
"技"
"术"
"算"
"法"
"T"
"e"
"n"
"s"
"o"
"r"
"F"
"l"
"o"
"w"
"进"
"阶"
"指"
"南"
4.4 peek
对流中的元素进行遍历,但不会销毁对象
list.stream().peek(sku -> System.out.println(sku.getSkuName())).forEach(
item -> System.out.println(JSON.toJSONString(item,true))
);
无人机
{
"skuCategory":"ELECTRONICS",
"skuId":654032,
"skuName":"无人机",
"skuPrice":4999.0,
"totalNum":1,
"totalPrice":4999.0
}
VR一体机
{
"skuCategory":"ELECTRONICS",
"skuId":642934,
"skuName":"VR一体机",
"skuPrice":2299.0,
"totalNum":1,
"totalPrice":2299.0
}
纯色衬衫
{
"skuCategory":"CLOTHING",
"skuId":645321,
"skuName":"纯色衬衫",
"skuPrice":409.0,
"totalNum":3,
"totalPrice":1227.0
}
牛仔裤
{
"skuCategory":"CLOTHING",
"skuId":654327,
"skuName":"牛仔裤",
"skuPrice":528.0,
"totalNum":1,
"totalPrice":528.0
}
跑步机
{
"skuCategory":"SPORTS",
"skuId":675489,
"skuName":"跑步机",
"skuPrice":2699.0,
"totalNum":1,
"totalPrice":2699.0
}
Java编程思想
{
"skuCategory":"BOOKS",
"skuId":644564,
"skuName":"Java编程思想",
"skuPrice":79.8,
"totalNum":1,
"totalPrice":79.8
}
Java核心技术
{
"skuCategory":"BOOKS",
"skuId":678678,
"skuName":"Java核心技术",
"skuPrice":149.0,
"totalNum":1,
"totalPrice":149.0
}
算法
{
"skuCategory":"BOOKS",
"skuId":697894,
"skuName":"算法",
"skuPrice":78.2,
"totalNum":1,
"totalPrice":78.2
}
TensorFlow进阶指南
{
"skuCategory":"BOOKS",
"skuId":696968,
"skuName":"TensorFlow进阶指南",
"skuPrice":85.1,
"totalNum":1,
"totalPrice":85.1
}
4.5 sort
对流中元素进行排序,可以选择自然排序或者指定排序规则
list.stream().sorted(Comparator.comparing(Sku::getTotalPrice)).forEach(
item -> System.out.println(JSON.toJSONString(item,true))
);
{
"skuCategory":"BOOKS",
"skuId":697894,
"skuName":"算法",
"skuPrice":78.2,
"totalNum":1,
"totalPrice":78.2
}
{
"skuCategory":"BOOKS",
"skuId":644564,
"skuName":"Java编程思想",
"skuPrice":79.8,
"totalNum":1,
"totalPrice":79.8
}
{
"skuCategory":"BOOKS",
"skuId":696968,
"skuName":"TensorFlow进阶指南",
"skuPrice":85.1,
"totalNum":1,
"totalPrice":85.1
}
{
"skuCategory":"BOOKS",
"skuId":678678,
"skuName":"Java核心技术",
"skuPrice":149.0,
"totalNum":1,
"totalPrice":149.0
}
{
"skuCategory":"CLOTHING",
"skuId":654327,
"skuName":"牛仔裤",
"skuPrice":528.0,
"totalNum":1,
"totalPrice":528.0
}
{
"skuCategory":"CLOTHING",
"skuId":645321,
"skuName":"纯色衬衫",
"skuPrice":409.0,
"totalNum":3,
"totalPrice":1227.0
}
{
"skuCategory":"ELECTRONICS",
"skuId":642934,
"skuName":"VR一体机",
"skuPrice":2299.0,
"totalNum":1,
"totalPrice":2299.0
}
{
"skuCategory":"SPORTS",
"skuId":675489,
"skuName":"跑步机",
"skuPrice":2699.0,
"totalNum":1,
"totalPrice":2699.0
}
{
"skuCategory":"ELECTRONICS",
"skuId":654032,
"skuName":"无人机",
"skuPrice":4999.0,
"totalNum":1,
"totalPrice":4999.0
}
4.6 distinct
对流中元素进行去重
//对类别进行去重
list.stream().map(Sku::getSkuCategory).distinct().forEach(
item -> System.out.println(JSON.toJSONString(item,true))
);
"ELECTRONICS"
"CLOTHING"
"SPORTS"
"BOOKS"
4.7 skip
跳过前N条记录
# 总价格按照从低到高排序,并跳过前3个
list.stream().sorted(Comparator.comparing(Sku::getTotalPrice))
.skip(3)
.forEach(
item -> System.out.println(JSON.toJSONString(item,true))
);
{
"skuCategory":"BOOKS",
"skuId":678678,
"skuName":"Java核心技术",
"skuPrice":149.0,
"totalNum":1,
"totalPrice":149.0
}
{
"skuCategory":"CLOTHING",
"skuId":654327,
"skuName":"牛仔裤",
"skuPrice":528.0,
"totalNum":1,
"totalPrice":528.0
}
{
"skuCategory":"CLOTHING",
"skuId":645321,
"skuName":"纯色衬衫",
"skuPrice":409.0,
"totalNum":3,
"totalPrice":1227.0
}
{
"skuCategory":"ELECTRONICS",
"skuId":642934,
"skuName":"VR一体机",
"skuPrice":2299.0,
"totalNum":1,
"totalPrice":2299.0
}
{
"skuCategory":"SPORTS",
"skuId":675489,
"skuName":"跑步机",
"skuPrice":2699.0,
"totalNum":1,
"totalPrice":2699.0
}
{
"skuCategory":"ELECTRONICS",
"skuId":654032,
"skuName":"无人机",
"skuPrice":4999.0,
"totalNum":1,
"totalPrice":4999.0
}
4.8 limit
截断前n条记录
list.stream().sorted(Comparator.comparing(Sku::getTotalPrice))
.limit(5)
.forEach(
item -> System.out.println(JSON.toJSONString(item,true))
);
{
"skuCategory":"BOOKS",
"skuId":697894,
"skuName":"算法",
"skuPrice":78.2,
"totalNum":1,
"totalPrice":78.2
}
{
"skuCategory":"BOOKS",
"skuId":644564,
"skuName":"Java编程思想",
"skuPrice":79.8,
"totalNum":1,
"totalPrice":79.8
}
{
"skuCategory":"BOOKS",
"skuId":696968,
"skuName":"TensorFlow进阶指南",
"skuPrice":85.1,
"totalNum":1,
"totalPrice":85.1
}
{
"skuCategory":"BOOKS",
"skuId":678678,
"skuName":"Java核心技术",
"skuPrice":149.0,
"totalNum":1,
"totalPrice":149.0
}
{
"skuCategory":"CLOTHING",
"skuId":654327,
"skuName":"牛仔裤",
"skuPrice":528.0,
"totalNum":1,
"totalPrice":528.0
}
4.9AllMatch/anyMatch/noneMatch
-
AllMatch:所有元素匹配,返回true
-
anyMatch:任何元素匹配,返回true
-
noneMatch:任何元素都不匹配,返回true
/**
* allMatch使用: 操作,短路操作。所有元素匹配,返回true
*/
@Test
public void allMatchTest(){
boolean match = list.stream()
.allMatch(sku -> sku.getTotalPrice()>100);
System.out.println(match);
}
/**
* anyMatch使用:任何元素匹配,返回true
*/
@Test
public void anyMatchTest(){
boolean match = list.stream()
.anyMatch(sku -> sku.getTotalPrice()>100);
System.out.println(match);
}
/**
* noneMatch使用:任何元素都不匹配,返回true
*/
@Test
public void testNoneMatch(){
boolean match = list.stream()
.noneMatch(sku -> sku.getTotalPrice()<0);
System.out.println(match);
}
4.10 findFirst/findAny
- findFirst:找到第一个
- findAny:找到任意一个
/**
* 找到第一个
*/
@Test
public void findFirstTest(){
Optional<Sku> optional = list.stream()
.peek(sku -> System.out.println(sku.getSkuName()))
.findFirst();
System.out.println(JSON.toJSONString(optional.get(),true));
}
/**
* 找到任意一个
*/
@Test
public void findAnyTest(){
Optional<Sku> optional = list.stream()
.peek(sku -> System.out.println(sku.getSkuName()))
.findAny();
System.out.println(JSON.toJSONString(optional.get(),true));
}
4.11 min/max/count
- min: 找出最小的项
- max:找出最大的项
- count:统计总数
@Test
public void maxTest(){
OptionalDouble optionalDouble = list.stream()
// 获取总价
.mapToDouble(Sku::getTotalPrice)
.max();
System.out.println(optionalDouble.getAsDouble());
}
@Test
public void minTest(){
OptionalDouble optionalDouble = list.stream()
// 获取总价
.mapToDouble(Sku::getTotalPrice)
.min();
System.out.println(optionalDouble.getAsDouble());
}
/**
* count
*/
@Test
public void countTest(){
long count = list.stream().count();
System.out.println(count);
}
5.流的收集
5.1 toList
将处理后的结果收集为list
// 收集总价格超过100的Sku
List<Sku> cartSkuList = CartService.getCartSkuList();
List<Sku> result = cartSkuList
.stream()
.filter(sku -> sku.getTotalPrice() > 100)
.collect(Collectors.toList());
System.out.println(JSON.toJSONString(result,true));
输出结果
[
{
"skuCategory":"ELECTRONICS",
"skuId":654032,
"skuName":"无人机",
"skuPrice":4999.0,
"totalNum":1,
"totalPrice":4999.0
},
{
"skuCategory":{"$ref":"$[0].skuCategory"},
"skuId":642934,
"skuName":"VR一体机",
"skuPrice":2299.0,
"totalNum":1,
"totalPrice":2299.0
},
{
"skuCategory":"CLOTHING",
"skuId":645321,
"skuName":"纯色衬衫",
"skuPrice":409.0,
"totalNum":3,
"totalPrice":1227.0
},
{
"skuCategory":{"$ref":"$[0][2].skuCategory"},
"skuId":654327,
"skuName":"牛仔裤",
"skuPrice":528.0,
"totalNum":1,
"totalPrice":528.0
},
{
"skuCategory":"SPORTS",
"skuId":675489,
"skuName":"跑步机",
"skuPrice":2699.0,
"totalNum":1,
"totalPrice":2699.0
},
{
"skuCategory":"BOOKS",
"skuId":678678,
"skuName":"Java核心技术",
"skuPrice":149.0,
"totalNum":1,
"totalPrice":149.0
}
]
5.3 toMap
@Test
public void testMapTest(){
List<Sku> cartSkuList = CartService.getCartSkuList();
//如果两个id重复,两个value可以映射到同一个id,如 678678重复
Map<Integer, String> map = cartSkuList.stream().collect(Collectors.toMap(Sku::getSkuId, Sku::getSkuName,
(e1, e2) -> e1 + "," + e2));
System.out.println(map.get(678678));
System.out.println(JSON.toJSONString(map,true));
}
Java核心技术
{
645321:"纯色衬衫",
696968:"TensorFlow进阶指南",
654032:"无人机",
675489:"跑步机",
697878:"算法",
678678:"Java核心技术",
644564:"Java编程思想",
654327:"牛仔裤",
642934:"VR一体机"
}
详细关于toMap方法可参考博客https://blog.csdn.net/goldfishsky/article/details/126260153
5.3 groupBy
按照指定条件进行分组
@Test
public void groupTest(){
List<Sku> cartSkuList = CartService.getCartSkuList();
Map<Enum, List<Sku>> group = cartSkuList
.stream()
.collect(Collectors.groupingBy(sku -> sku.getSkuCategory()));
System.out.println(JSON.toJSONString(group,true));
}
{
"SPORTS":[
{
"skuCategory":"SPORTS",
"skuId":675489,
"skuName":"跑步机",
"skuPrice":2699.0,
"totalNum":1,
"totalPrice":2699.0
}
],
"BOOKS":[
{
"skuCategory":"BOOKS",
"skuId":644564,
"skuName":"Java编程思想",
"skuPrice":79.8,
"totalNum":1,
"totalPrice":79.8
},
{
"skuCategory":{"$ref":"$[0][0].skuCategory"},
"skuId":678678,
"skuName":"Java核心技术",
"skuPrice":149.0,
"totalNum":1,
"totalPrice":149.0
},
{
"skuCategory":{"$ref":"$[0][0].skuCategory"},
"skuId":697894,
"skuName":"算法",
"skuPrice":78.2,
"totalNum":1,
"totalPrice":78.2
},
{
"skuCategory":{"$ref":"$[0][0].skuCategory"},
"skuId":696968,
"skuName":"TensorFlow进阶指南",
"skuPrice":85.1,
"totalNum":1,
"totalPrice":85.1
}
],
"CLOTHING":[
{
"skuCategory":"CLOTHING",
"skuId":645321,
"skuName":"纯色衬衫",
"skuPrice":409.0,
"totalNum":3,
"totalPrice":1227.0
},
{
"skuCategory":{"$ref":"$[0][0][0].skuCategory"},
"skuId":654327,
"skuName":"牛仔裤",
"skuPrice":528.0,
"totalNum":1,
"totalPrice":528.0
}
],
"ELECTRONICS":[
{
"skuCategory":"ELECTRONICS",
"skuId":654032,
"skuName":"无人机",
"skuPrice":4999.0,
"totalNum":1,
"totalPrice":4999.0
},
{
"skuCategory":{"$ref":"$[0][0][0][0].skuCategory"},
"skuId":642934,
"skuName":"VR一体机",
"skuPrice":2299.0,
"totalNum":1,
"totalPrice":2299.0
}
]
}
5.4 partition
按分区条件进行筛选
List<Sku> cartSkuList = CartService.getCartSkuList();
Map<Boolean, List<Sku>> result =
cartSkuList.stream()
.collect(
Collectors
.partitioningBy(sku -> sku.getTotalPrice() > 100));
System.out.println(JSON.toJSONString(result,true));
{
false:[
{
"skuCategory":"BOOKS",
"skuId":644564,
"skuName":"Java编程思想",
"skuPrice":79.8,
"totalNum":1,
"totalPrice":79.8
},
{
"skuCategory":{"$ref":"$[0].skuCategory"},
"skuId":697878,
"skuName":"算法",
"skuPrice":78.2,
"totalNum":1,
"totalPrice":78.2
},
{
"skuCategory":{"$ref":"$[0].skuCategory"},
"skuId":696968,
"skuName":"TensorFlow进阶指南",
"skuPrice":85.1,
"totalNum":1,
"totalPrice":85.1
}
],
true:[
{
"skuCategory":"ELECTRONICS",
"skuId":654032,
"skuName":"无人机",
"skuPrice":4999.0,
"totalNum":1,
"totalPrice":4999.0
},
{
"skuCategory":{"$ref":"$[0][0].skuCategory"},
"skuId":642934,
"skuName":"VR一体机",
"skuPrice":2299.0,
"totalNum":1,
"totalPrice":2299.0
},
{
"skuCategory":"CLOTHING",
"skuId":645321,
"skuName":"纯色衬衫",
"skuPrice":409.0,
"totalNum":3,
"totalPrice":1227.0
},
{
"skuCategory":{"$ref":"$[0][0][2].skuCategory"},
"skuId":654327,
"skuName":"牛仔裤",
"skuPrice":528.0,
"totalNum":1,
"totalPrice":528.0
},
{
"skuCategory":"SPORTS",
"skuId":675489,
"skuName":"跑步机",
"skuPrice":2699.0,
"totalNum":1,
"totalPrice":2699.0
},
{
"skuCategory":{"$ref":"$[0].skuCategory"},
"skuId":678678,
"skuName":"Java核心技术",
"skuPrice":149.0,
"totalNum":1,
"totalPrice":149.0
}
]
}