一、什么是Stream类
- 原始的集合数据类似于数据的输入
- 流式处理是对输入数据进行处理
- 处理后的数据进行汇集类似于数据输出
Stream像一个流水线作业,主要分成流水线处理和最终的汇集聚合,其作用对象是集合数据
- 流式处理(stream相关方法)
- 数据汇集(collect方法)
二、Stream类主要作用
对集合数据进行以下处理:
- 查找
- 筛选过滤
- 计算
- 组合
- 排序
- 匹配
三、Stream类主要方法
- 定义一个供操作的对象:中奖记录对象AwardRecord
/**
* 中奖记录
* @author shixinke
* @date 2019-1-30
*/
class AwardRecord {
/**
* 记录ID
*/
private Long recordId;
/**
* 中奖用户ID
*/
private Long userId;
/**
* 数量
*/
private Integer num;
/**
* 中奖物品ID
*/
private Long itemId;
/**
* 中奖物品的单个价值
*/
private Double worth;
public Long getRecordId() {
return recordId;
}
public void setRecordId(Long recordId) {
this.recordId = recordId;
}
public Long getUserId() {
return userId;
}
public void setUserId(Long userId) {
this.userId = userId;
}
public Integer getNum() {
return num;
}
public void setNum(Integer num) {
this.num = num;
}
public Long getItemId() {
return itemId;
}
public void setItemId(Long itemId) {
this.itemId = itemId;
}
public Double getWorth() {
return worth;
}
public void setWorth(Double worth) {
this.worth = worth;
}
public AwardRecord(Long recordId, Long userId, Integer num, Long itemId, Double worth) {
this.recordId = recordId;
this.userId = userId;
this.num = num;
this.itemId = itemId;
this.worth = worth;
}
@Override
public String toString() {
return "AwardRecord{" +
"recordId=" + recordId +
", userId=" + userId +
", num=" + num +
", itemId=" + itemId +
", worth=" + worth +
'}';
}
}
public class CollectorDemo {
public static void main(String[] args) {
List<AwardRecord> awardRecordList = new ArrayList<AwardRecord>(5);
awardRecordList.add(new AwardRecord(300001L, 5000001L, 1, 8754578L, 1.35));
awardRecordList.add(new AwardRecord(300002L, 5200001L, 2, 8754579L, 2.35));
awardRecordList.add(new AwardRecord(300003L, 5000001L, 1, 8754878L, 0.35));
awardRecordList.add(new AwardRecord(300004L, 5300001L, 3, 8354578L, 0.21));
awardRecordList.add(new AwardRecord(300005L, 5200001L, 1, 8154578L, 2.63));
}
}
注:通过集合对象的stream方法就可以得到一个Stream对象
1.查找
- 查找满足条件的第一个元素 : findFirst
- 查找满足条件的任意一个元素 : findAny
/**
* 1.查找第一个集合元素
*/
Optional<AwardRecord> recordOptional = awardRecordList.stream().findFirst();
System.out.println(recordOptional.get()); //AwardRecord{recordId=300001, userId=5000001, num=1, itemId=8754578, worth=1.35}
/**
* 2.查找任意一个元素
*/
Optional<AwardRecord> recordAnyOptional =awardRecordList.stream().filter(c -> c.getWorth() < 1).findAny();
System.out.println(recordAnyOptional.get()); //AwardRecord{recordId=300003, userId=5000001, num=1, itemId=8754878, worth=0.35}
2.筛选过滤
(1)内容过滤
- filter : 通过一个过滤函数筛选元素
- distinct : 元素去重
/**
* 3.获取奖励数量大于等于2的中奖记录
*/
List<AwardRecord> recordList = awardRecordList.stream().filter(c -> c.getNum() >= 2).collect(Collectors.toList());
System.out.println(recordList); //[AwardRecord{recordId=300002, userId=5200001, num=2, itemId=8754579, worth=2.35}, AwardRecord{recordId=300004, userId=5300001, num=3, itemId=8354578, worth=0.21}]
/**
* 4.中奖用户列表
*/
List<Long> userList = awardRecordList.stream().map(AwardRecord::getUserId).distinct().collect(Collectors.toList());
System.out.println(userList); //[5000001, 5200001, 5300001]
(2)数量限制
- limit : 获取指定数量的元素
- skip : 跳过指定数量的元素
/**
* 5.只展示前3条数据
*/
List<AwardRecord> topList = awardRecordList.stream().limit(3).collect(Collectors.toList());
System.out.println(topList); //[AwardRecord{recordId=300001, userId=5000001, num=1, itemId=8754578, worth=1.35}, AwardRecord{recordId=300002, userId=5200001, num=2, itemId=8754579, worth=2.35}, AwardRecord{recordId=300003, userId=5000001, num=1, itemId=8754878, worth=0.35}]
/**
* 6.只展示后3位
*/
List<AwardRecord> lastList = awardRecordList.stream().skip(2).limit(3).collect(Collectors.toList());
System.out.println(lastList); //[AwardRecord{recordId=300001, userId=5000001, num=1, itemId=8754578, worth=1.35}, AwardRecord{recordId=300002, userId=5200001, num=2, itemId=8754579, worth=2.35}, AwardRecord{recordId=300003, userId=5000001, num=1, itemId=8754878, worth=0.35}]
注:通过skip和limit可以实现简单的分页
- skip的参数可以认为是起始索引
- limit为每页显示数
3.计算
- count : 计算满足条件的集合元素的数量
- min : 计算满足条件的最小的元素
- max : 计算满足条件的最大的元素
/**
* 7.计算数量(中奖用户数量)
*/
Long dataCount = awardRecordList.stream().map(AwardRecord::getUserId).distinct().count();
System.out.println(dataCount); //3
/**
* 8.计算价值最小的中奖记录
*/
Optional<AwardRecord> minRecord = awardRecordList.stream().min(Comparator.comparing(AwardRecord::getWorth));
System.out.println(minRecord.get().getWorth()); //0.21
/**
* 9.计算价值最大的中奖记录
*/
Optional<AwardRecord> maxRecord = awardRecordList.stream().max(Comparator.comparing(AwardRecord::getWorth));
System.out.println(maxRecord.get().getWorth()); //2.63
4.组合
- map : 对元素进行进行重新组合
- reduce : 对元素进行计算形成一个结果
/**
* 通过map对元素进行重新组合(如获取原对象的部分数据形成新的集合),如:获取中奖用户列表
*/
List<Long> userList = awardRecordList.stream().map(AwardRecord::getUserId).distinct().collect(Collectors.toList());
System.out.println(userList);
5.排序
- sorted
- 实现Comparator接口的compare抽象方法
- 使用Comparator接口的静态方法comparing等方法
- 一般使用Comparators工具类来实现排序操作
System.out.println(awardRecordList.stream().sorted(Comparator.comparing(AwardRecord::getWorth).reversed()).collect(Collectors.toList()));
List<AwardRecord> topList = awardRecordList.stream().sorted(
((AwardRecord r1, AwardRecord r2) ->
Double.valueOf(r1.getNum() * r1.getWorth()).compareTo(Double.valueOf(r2.getNum() * r2.getWorth())))
).collect(Collectors.toList());
Comparators的使用请参考 Comparators工具类的使用
6.收集
- collect:将流处理的数据进行汇集,通过Collector接口或者Collectors工具类来实现
- Collector接口:实现Collector接口
- Collectors工具类:一般使用Collectors类来进行数据收集
Collectors的使用请参考 Collectors工具类的使用