• 【java8】阿里架构师:Stream对集合的处理方式你全都知道了吗?


     一、概述

    Stream 是 Java8 中处理集合的关键抽象概念,它可以指定你希望对集合进行的操作,可以执行非常复杂的查找、过滤和映射数据等操作。使用Stream API 对集合数据进行操作,就类似于使用 SQL 执行的数据库查询。也可以使用 Stream API来并行执行操作。简而言之,Stream API 提供了一种高效且易于使用的处理数据的方式。

    特点:

    • 元素是特定类型的对象,形成一个队列。 Java中的Stream并不会存储元素,而是按需计算。

    • 数据源 流的来源。 可以是集合,数组,I/O channel, 产生器generator 等。

    • 聚合操作 类似SQL语句一样的操作, 比如filter, map, reduce, find, match, sorted等。

    • Pipelining: 中间操作都会返回流对象本身。 这样多个操作可以串联成一个管道, 如同流式风格(fluent style)。 这样做可以对操作进行优化, 比如延迟执行(laziness)和短路( short-circuiting)。

    • 内部迭代: 以前对集合遍历都是通过Iterator或者For-Each的方式, 显式的在集合外部进行迭代, 这叫做外部迭代。 Stream提供了内部迭代的方式, 通过访问者模式(Visitor)实现。

    二、Stream的创建

    Stream可以通过集合数组创建。

    1、通过 java.util.Collection.stream() 方法用集合创建流

    1. List<Integer> list = Arrays.asList(1, 2, 3);
    2. // 创建一个顺序流
    3. Stream<Integer> stream = list.stream();
    4. // 创建一个并行流
    5. Stream<Integer> parallelStream = list.parallelStream();

    2、使用java.util.Arrays.stream(T[] array)方法用数组创建流

    1. int[] array={1,3,5,6,8};
    2. IntStream stream = Arrays.stream(array);

    3、使用Stream的静态方法:of()、iterate()、generate()(我不是很常用)

    1. Stream<Integer> stream = Stream.of(1, 2, 3);
    2. // of内部的方法,等同于使用数组创建流
    3. @SafeVarargs
    4. @SuppressWarnings("varargs") // Creating a stream from an array is safe
    5. public static<T> Stream<T> of(T... values) {
    6. return Arrays.stream(values);
    7. }
    8. Stream<Integer> stream2 = Stream.iterate(0, (x) -> x + 3).limit(4);
    9. stream2.forEach(System.out::print);
    10. System.out.println();
    11. Stream<Double> stream3 = Stream.generate(Math::random).limit(3);
    12. stream3.forEach(System.out::println);

    输出结果:

    1. 0369
    2. 0.4918954920054893
    3. 0.8246638264369555
    4. 0.17880449237798712

    将对象集合转成对象中某个属性的集合

    1. List<ReviewerRest> list = new ArrayList<>();
    2. List<Long> ids = list.stream().map(ReviewerRest::getId).collect(Collectors.toList());
    3. 复制代码

    将某个属性的集合转成对象集合

    1. List<Long> ids = new ArrayList<>();
    2. List<ReviewerRest> list = ids.stream().map(id -> {
    3. ReviewerRest rest = new ReviewerRest();
    4. rest.setRest(1);
    5. rest.setDate(LocalDate.now());
    6. rest.setReviewerId(1000L);
    7. return rest;
    8. }).collect(Collectors.toList());
    9. 复制代码

    判断集合中是否有一个对象包含某个属性

    1. boolean exist = list.stream().anyMatch(rest -> rest.getReviewerId().equals(1000L));
    2. //...... allMatch 和 anyMatch 类似
    3. 复制代码

    对集合中某个对象的属性求和

    1. BigDecimal reduce = list.stream().map(ReviewerRest::getPrice).reduce(BigDecimal.ZERO, BigDecimal::add);
    2. 复制代码

    集合转 Map (普通)

    1. Map<Long, ReviewerRest> map = list.stream().collect(Collectors.toMap(ReviewerRest::getId, x -> x));
    2. 复制代码

    集合转 Map (key 存在重复)

    当集合中 id 会存在重复时,上面那种方式会报错,此时需要指定重复时选用哪一个 value

    1. Map<Long, ReviewerRest> map = list.stream().collect(Collectors.toMap(ReviewerRest::getId, x -> x, (before, after) -> after));
    2. 复制代码

    集合转 Map (value 存在 null 值)

    当 value 存在 null 值时上面那种方式会报错,此时需要换一种写法

    1. Map<Long, LocalDate> map = list.stream().collect(HashMap::new, (mapItem, item) -> mapItem.put(item.getId(), item.getDate()), HashMap::putAll);
    2. 复制代码

    集合分组 转 Map

    1. Map<Long, List<ReviewerRest>> map = list.stream().collect(Collectors.groupingBy(ReviewerRest::getId));
    2. 复制代码

    集合分区 转 Map

    1. Map<Boolean, List<ReviewerRest>> map = list.stream().collect(Collectors.partitioningBy(r -> r.getRest() == 1));
    2. 复制代码

    集合分组个数统计

    1. Map<Long, Long> map = list.stream().collect(Collectors.groupingBy(ReviewerRest::getId,Collectors.counting()));
    2. 复制代码

    集合分组转某个属性集合

    1. Map<Long, List<Integer>> map = list.stream().collect(Collectors.groupingBy(ReviewerRest::getId,Collectors.mapping(ReviewerRest::getRest,Collectors.toList())));
    2. 复制代码

    集合分组聚合查询最大元素

    1. Map<Long, Optional<ReviewerRest>> map = list.stream().collect(Collectors.groupingBy(ReviewerRest::getReviewerId, Collectors.maxBy(Comparator.comparing(ReviewerRest::getDate))));
    2. 复制代码

    集合分组聚合求和

    1. //目前只支持 int、double、long
    2. Map<Long, Long> map = list.stream().collect(Collectors.groupingBy(ReviewerRest::getReviewerId, Collectors.summingLong(

    java8采用stream对集合的常用操作

    1. User :{
    2. id,
    3. name,
    4. age
    5. }

    1.对象集合的分组(有两种形式)
    示例:List userList,根据id分组,可以分组成为两种格式的map
    (1)Map

    Map<id,User> map = userList.stream().collect(Collectors.toMap(User::getId, Function.identity()));
    

    (2)Map

    Map<id,List<User>> = userList.stream().collect(Collectors.groupingBy(User::getId));
    

    2.去重操作
    对List 实现去重,distinct关键字

    示例:userList= userList.stream().distinct().collect(Collectors.toList());
    

    3.stream的map
    主要用于得到特定的结构
    例如:List userList,我向得到User Id的集合

    List<Integer> idList = userList.stream.map(User::getId).collect(Collectors.toList());
    

    4.stream的filter
    主要用于数据的筛选。
    例1:一个条件的筛选,删选id>5的User

    List<UserList> userList = userList.stream.filter(i->i.getId()>5).collect(Collectors.toList());
    

    例2:两个条件的删选用&&连接就行,删选id>5年纪>10的User

    List<UserList> userList = userList.stream.filter(i->i.getId()>5&&i.getAge()>10).collect(Collectors.toList());
    

    5.用来作循环

    userList.stream().forEach(user -> System.out.println("姓名:" + user.getName()));
    


    当然也可以加个limit限制数量

    userList.stream().limit(2).forEach(user -> System.out.println("姓名:" + user.getName()));
    


    6.最大值最小值

    1. int maxAge = userList.stream().mapToInt(User::getAge).max().getAsInt();
    2. int minAge = userList.stream().mapToInt(User::getAge).min().getAsInt();

    封装的Stream使用类,可以直接拿走使用:

    1. public class StreamUtils {
    2. /**
    3. * 集合为空,创建空的Stream流;否则创建集合的Stream流
    4. * 避免出现空指针
    5. *
    6. * @param collection 集合
    7. * @param 集合元素的泛型
    8. * @return Stream对象
    9. */
    10. private static <T> Stream<T> streamOf(Collection<T> collection) {
    11. return CollectionUtils.isEmpty(collection) ? Stream.empty() : collection.stream();
    12. }
    13. /**
    14. * 按照映射规则映射成一个新的集合流
    15. *
    16. * @param list 集合
    17. * @param mapper 集合属性元素
    18. * @param 函数输入类型的泛型
    19. * @param 函数结果类型的泛型
    20. * @return 新的集合
    21. */
    22. public static <T, R> List<R> mapList(List<T> list, Function<? super T, ? extends R> mapper) {
    23. return streamOf(list).map(mapper).collect(Collectors.toList());
    24. }
    25. /**
    26. * 根据给定的条件进行筛选,将符合条件的元素提取成新的流
    27. *
    28. * @param list 集合
    29. * @param predicate 筛选规则
    30. * @param 流元素的类型
    31. * @return 符合条件的流集合
    32. */
    33. public static <T> List<T> filter(List<T> list, Predicate<? super T> predicate) {
    34. return streamOf(list).filter(predicate).collect(Collectors.toList());
    35. }
    36. /**
    37. * 根据给定的条件进行筛选,将符合条件的元素提取成新的流
    38. *
    39. * @param list 集合
    40. * @param predicates 多个筛选条件
    41. * @param 流元素的类型
    42. * @return 符合条件的流集合
    43. */
    44. @SafeVarargs
    45. public static <T> List<T> filters(List<T> list, Predicate<? super T> ... predicates) {
    46. Stream<T> stream = streamOf(list);
    47. for (Predicate<? super T> predicate : predicates) {
    48. stream = stream.filter(predicate);
    49. }
    50. return stream.collect(Collectors.toList());
    51. }
    52. /**
    53. * 根据指定元素对集合进行升序排序
    54. *
    55. * @param list 集合
    56. * @param keyExtractor 用来排序的元素
    57. * @param 函数输入类型的泛型
    58. * @param 函数结果类型的泛型
    59. * @return 排序后的集合
    60. */
    61. public static <T, U extends Comparable<? super U>> List sorted(
    62. List<T> list, Function<? super T, ? extends U> keyExtractor) {
    63. return streamOf(list).sorted(Comparator.comparing(keyExtractor)).collect(Collectors.toList());
    64. }
    65. /**
    66. * 根据指定元素对集合进行升序排序
    67. *
    68. * @param list 集合
    69. * @param keyExtractor 用来排序的元素
    70. * @param limit 排序后集合中保留的数量
    71. * @param 函数输入类型的泛型
    72. * @param 函数结果类型的泛型
    73. * @return 排序后的集合
    74. */
    75. public static <T, U extends Comparable<? super U>> List sorted(
    76. List<T> list, Function<? super T, ? extends U> keyExtractor, Integer limit) {
    77. return streamOf(list).sorted(Comparator.comparing(keyExtractor)).limit(limit).collect(Collectors.toList());
    78. }
    79. /**
    80. * 根据指定元素对集合进行降序排序
    81. *
    82. * @param list 集合
    83. * @param keyExtractor 用来排序的元素
    84. * @param 函数输入类型的泛型
    85. * @param 函数结果类型的泛型
    86. * @return 排序后的集合
    87. */
    88. public static <T, U extends Comparable<? super U>> List sortedDesc(
    89. List<T> list, Function<? super T, ? extends U> keyExtractor) {
    90. return streamOf(list).sorted(Comparator.comparing(keyExtractor).reversed()).collect(Collectors.toList());
    91. }
    92. /**
    93. *根据规则判断元素是否匹配
    94. *
    95. * @param list 集合
    96. * @param predicate 匹配规则
    97. * @param 元素类型
    98. * @return 匹配结果
    99. */
    100. public static <T> boolean anyMatch(List<T> list, Predicate<? super T> predicate) {
    101. return streamOf(list).anyMatch(predicate);
    102. }
    103. /**
    104. * 将List集合转换成Map集合,同一个key时对value进行去重,保留第一个出现的value值
    105. *
    106. * @param list 集合
    107. * @param keyMapper 新的Map中的key
    108. * @param 参数的类型
    109. * @return 转换后的Map集合
    110. */
    111. public static <T, K> Map< K, T> toMapDistinctFirst(List<T> list, Function<? super T, ? extends K> keyMapper) {
    112. return streamOf(list).collect(Collectors.toMap(keyMapper, Function.identity(), (key1, key2) -> key1));
    113. }
    114. /**
    115. * 将List集合转换成Map集合,同一个key时对value进行去重,保留最后出现的value值
    116. *
    117. * @param list 集合
    118. * @param keyMapper 新的Map中的key
    119. * @param 参数的类型
    120. * @return 转换后的Map集合
    121. */
    122. public static <T, K> Map<K, T> toMapDistinctLast(List<T> list, Function<? super T, ? extends K> keyMapper) {
    123. return streamOf(list).collect(Collectors.toMap(keyMapper, Function.identity(), (key1, key2) -> key2));
    124. }
    125. /**
    126. * 将List转换为指定key->value键值对元素的Map集合
    127. * @param list 集合
    128. * @param keyMapper Map的key元素
    129. * @param valueMapper Map的value元素
    130. * @param 函数输入的类型
    131. * @param 函数输出的类型
    132. * @param 函数输出的类型
    133. * @return 转换后的Map集合
    134. */
    135. public static <T, K, U> Map<K, U> toMap(List<T> list, Function<? super T, ? extends K> keyMapper,
    136. Function<? super T, ? extends U> valueMapper) {
    137. return streamOf(list).collect(Collectors.toMap(keyMapper, valueMapper));
    138. }
    139. }

    最后希望大家能从文章中得到帮助获得收获,也可以评论出你想看哪方面的技术。文章会持续更新,希望能帮助到大家,哪怕是让你灵光一现。喜欢的朋友可以点点赞和关注,也可以分享出去让更多的人看见,一起努力一起进步!

  • 相关阅读:
    Java基础空指针
    Nginx(四) absolute_redirect、server_name_in_redirect、port_in_redirect 请求重定向指令组合测试
    idea文件及方法注释
    氨基NH2/羧基COOH修饰/偶联/接枝NaY(Gd/Lu/Nd)F4:Yb,Tm核壳上转换纳米粒子
    力扣刷题day39|70. 爬楼梯(进阶版)、322零钱兑换、279完全平方数
    【kaggle】AI Report 2023概览
    学信息系统项目管理师第4版系列35_补遗
    MacOS13-将数据库转为markdown,docx格式
    1.1 数据采集总览
    vue 复杂的流程图实现--antv/g6
  • 原文地址:https://blog.csdn.net/m0_73603837/article/details/126932055