Java8新特性(3).Stream流处理

一、什么是Stream类

stream流水线流程

  • 原始的集合数据类似于数据的输入
  • 流式处理是对输入数据进行处理
  • 处理后的数据进行汇集类似于数据输出

Stream像一个流水线作业,主要分成流水线处理和最终的汇集聚合,其作用对象是集合数据

  • 流式处理(stream相关方法)
  • 数据汇集(collect方法)

二、Stream类主要作用

对集合数据进行以下处理:

  • 查找
  • 筛选过滤
  • 计算
  • 组合
  • 排序
  • 匹配

三、Stream类主要方法

stream知识框架

  • 定义一个供操作的对象:中奖记录对象AwardRecord
  1. /**
  2. * 中奖记录
  3. * @author shixinke
  4. * @date 2019-1-30
  5. */
  6. class AwardRecord {
  7. /**
  8. * 记录ID
  9. */
  10. private Long recordId;
  11. /**
  12. * 中奖用户ID
  13. */
  14. private Long userId;
  15. /**
  16. * 数量
  17. */
  18. private Integer num;
  19. /**
  20. * 中奖物品ID
  21. */
  22. private Long itemId;
  23. /**
  24. * 中奖物品的单个价值
  25. */
  26. private Double worth;
  27. public Long getRecordId() {
  28. return recordId;
  29. }
  30. public void setRecordId(Long recordId) {
  31. this.recordId = recordId;
  32. }
  33. public Long getUserId() {
  34. return userId;
  35. }
  36. public void setUserId(Long userId) {
  37. this.userId = userId;
  38. }
  39. public Integer getNum() {
  40. return num;
  41. }
  42. public void setNum(Integer num) {
  43. this.num = num;
  44. }
  45. public Long getItemId() {
  46. return itemId;
  47. }
  48. public void setItemId(Long itemId) {
  49. this.itemId = itemId;
  50. }
  51. public Double getWorth() {
  52. return worth;
  53. }
  54. public void setWorth(Double worth) {
  55. this.worth = worth;
  56. }
  57. public AwardRecord(Long recordId, Long userId, Integer num, Long itemId, Double worth) {
  58. this.recordId = recordId;
  59. this.userId = userId;
  60. this.num = num;
  61. this.itemId = itemId;
  62. this.worth = worth;
  63. }
  64. @Override
  65. public String toString() {
  66. return "AwardRecord{" +
  67. "recordId=" + recordId +
  68. ", userId=" + userId +
  69. ", num=" + num +
  70. ", itemId=" + itemId +
  71. ", worth=" + worth +
  72. '}';
  73. }
  74. }
  75. public class CollectorDemo {
  76. public static void main(String[] args) {
  77. List<AwardRecord> awardRecordList = new ArrayList<AwardRecord>(5);
  78. awardRecordList.add(new AwardRecord(300001L, 5000001L, 1, 8754578L, 1.35));
  79. awardRecordList.add(new AwardRecord(300002L, 5200001L, 2, 8754579L, 2.35));
  80. awardRecordList.add(new AwardRecord(300003L, 5000001L, 1, 8754878L, 0.35));
  81. awardRecordList.add(new AwardRecord(300004L, 5300001L, 3, 8354578L, 0.21));
  82. awardRecordList.add(new AwardRecord(300005L, 5200001L, 1, 8154578L, 2.63));
  83. }
  84. }

注:通过集合对象的stream方法就可以得到一个Stream对象

1.查找
  • 查找满足条件的第一个元素 : findFirst
  • 查找满足条件的任意一个元素 : findAny
  1. /**
  2. * 1.查找第一个集合元素
  3. */
  4. Optional<AwardRecord> recordOptional = awardRecordList.stream().findFirst();
  5. System.out.println(recordOptional.get()); //AwardRecord{recordId=300001, userId=5000001, num=1, itemId=8754578, worth=1.35}
  6. /**
  7. * 2.查找任意一个元素
  8. */
  9. Optional<AwardRecord> recordAnyOptional =awardRecordList.stream().filter(c -> c.getWorth() < 1).findAny();
  10. System.out.println(recordAnyOptional.get()); //AwardRecord{recordId=300003, userId=5000001, num=1, itemId=8754878, worth=0.35}
2.筛选过滤
(1)内容过滤
  • filter : 通过一个过滤函数筛选元素
  • distinct : 元素去重
  1. /**
  2. * 3.获取奖励数量大于等于2的中奖记录
  3. */
  4. List<AwardRecord> recordList = awardRecordList.stream().filter(c -> c.getNum() >= 2).collect(Collectors.toList());
  5. 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}]
  6. /**
  7. * 4.中奖用户列表
  8. */
  9. List<Long> userList = awardRecordList.stream().map(AwardRecord::getUserId).distinct().collect(Collectors.toList());
  10. System.out.println(userList); //[5000001, 5200001, 5300001]
(2)数量限制
  • limit : 获取指定数量的元素
  • skip : 跳过指定数量的元素
  1. /**
  2. * 5.只展示前3条数据
  3. */
  4. List<AwardRecord> topList = awardRecordList.stream().limit(3).collect(Collectors.toList());
  5. 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. /**
  7. * 6.只展示后3位
  8. */
  9. List<AwardRecord> lastList = awardRecordList.stream().skip(2).limit(3).collect(Collectors.toList());
  10. 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 : 计算满足条件的最大的元素
  1. /**
  2. * 7.计算数量(中奖用户数量)
  3. */
  4. Long dataCount = awardRecordList.stream().map(AwardRecord::getUserId).distinct().count();
  5. System.out.println(dataCount); //3
  6. /**
  7. * 8.计算价值最小的中奖记录
  8. */
  9. Optional<AwardRecord> minRecord = awardRecordList.stream().min(Comparator.comparing(AwardRecord::getWorth));
  10. System.out.println(minRecord.get().getWorth()); //0.21
  11. /**
  12. * 9.计算价值最大的中奖记录
  13. */
  14. Optional<AwardRecord> maxRecord = awardRecordList.stream().max(Comparator.comparing(AwardRecord::getWorth));
  15. System.out.println(maxRecord.get().getWorth()); //2.63
4.组合
  • map : 对元素进行进行重新组合
  • reduce : 对元素进行计算形成一个结果
  1. /**
  2. * 通过map对元素进行重新组合(如获取原对象的部分数据形成新的集合),如:获取中奖用户列表
  3. */
  4. List<Long> userList = awardRecordList.stream().map(AwardRecord::getUserId).distinct().collect(Collectors.toList());
  5. System.out.println(userList);
5.排序
  • sorted
    • 实现Comparator接口的compare抽象方法
    • 使用Comparator接口的静态方法comparing等方法
    • 一般使用Comparators工具类来实现排序操作
  1. System.out.println(awardRecordList.stream().sorted(Comparator.comparing(AwardRecord::getWorth).reversed()).collect(Collectors.toList()));
  2. List<AwardRecord> topList = awardRecordList.stream().sorted(
  3. ((AwardRecord r1, AwardRecord r2) ->
  4. Double.valueOf(r1.getNum() * r1.getWorth()).compareTo(Double.valueOf(r2.getNum() * r2.getWorth())))
  5. ).collect(Collectors.toList());

Comparators的使用请参考 Comparators工具类的使用

6.收集
  • collect:将流处理的数据进行汇集,通过Collector接口或者Collectors工具类来实现
    • Collector接口:实现Collector接口
    • Collectors工具类:一般使用Collectors类来进行数据收集

Collectors的使用请参考 Collectors工具类的使用