• 基于Spring Boot应用Java的Stream流API


    记录:292

    场景:Stream流操作基本步骤一般归纳为:Stream流的创建、Stream流的中间操作、Stream流的终止操作。以数据源List为例,先把List转换为Stream;再对Stream进行中间操作,比如使用Stream的filter函数筛选;最后使用Stream的forEach遍历输出结果。

    版本:

    1. JDK 1.8
    2. Spring Boot 2.6.3

    一、基础

    1.函数式接口

    (1)使用@FunctionalInterface注解标记的接口,接口中有且只有一个抽象方法。

    (2)接口中的默认方法、静态方法等不计入抽象方法。

    (3)JDK 1.8及其后续版本。

    (4)函数入参中使用函数式接口,本质就是重写函数式接口中的抽象方法。

    (5)函数入参中有函数式接口定义的参数是,使用Lambda表达式或者匿名类实现抽象方法是常用的方式。

    (6)Stream流式编程中的API中大量使用了函数式接口作为入参。

    2.Lambda 表达式

    Lambda表达式,是Java 8 发布的重要特性。

    Lambda允许把函数作为一个方法的参数,即函数作为参数传递进方法中。

    Lambda表达式是代码变得更加简洁和紧凑。

    Lambda表达式语法规则:

    1. #方式一:
    2. (parameters) -> expression
    3. #方式二:
    4. (parameters) ->{ expression; }

    3.对理解

    理解,就是对泛型的理解。

    3.1 概念理解

    :表示?匹配的类型都是T的父类,包括T本身。

    :表示?匹配的类型都是类型R的子类,包括R本身

    3.2 使用List协助理解

    3.2.1 List<? super T>

    List list:表示集合中存放的都是T的父类(包括T本身)。

    针对变量List list。

    (1)对List做添加(add(T))操作,必须使用T或者T的子类添加到list中。

    (2)对List做遍历查询操作,必须使用T父类去遍历list,取出元素。

    小结:拿到一个变量使用? super T修饰时,应该是对该变量做添加操作,不做查询操作。这种方式修饰叫做put原则。

    3.2.2 List 

    List list:表示集合中存放的都是R的子类(包括R本身)。

    针对变量List list。

    (1)对List做添加(add(R))操作,必须使用R或者R的子类添加到list中。

    (2)对List做遍历查询操作,必须使用R遍历list,取出元素.

    小结:拿到一个变量使用? extends R修饰时,应该是对该变量做查询或取元素操作,不做添加操作。这种方式修饰叫做get原则。

    二、Stream基础

    1.Stream接口位置

    (1)在jdk中,java.util.stream包下,存放的都是Stream相关的接口和实现类。

    (2)在jdk中,Stream路径:java.util.stream.Stream。

    Stream是interface类型,继承BaseStream和AutoCloseable接口。

    BaseStream路径:java.util.stream.BaseStream。

    AutoCloseable路径:java.lang.AutoCloseable

    2.Stream理解

    Stream,基于lambda表达式,是对集合对象功能的增强,以一种声明的方式处理数据。可以执行过滤、映射数据、查找、聚合等操作。

    3.Stream操作

    Stream的操作,一般归纳为3个步骤。

    3.1 Stream流的创建

    要操作流,需获取流,可以从集合、数组、或者Stream的静态方法创建流。

    比如:

    (1)java.util.Collection的Stream stream()方法,那么实现Collection接口的类均可获取流。比如:java.util.List的实现类;java.util.Set的实现类;Map转换为流使用Map的entrySet等方法,这些方法返回值是Set。

    (2)java.util.Arrays的stream方法,可以把数组转换为Stream。而且Arrays工具类重载了各种型式的stream方法,可以满足大部分从数组转换为Stream的需求。

    (3)Stream的静态方法创建Stream流,比如of方法。

    3.2 Stream流的中间操作

    操作Stream流,比如filter过滤操作、map一个流转换为另一个流程、sorted排序、distinct去重等操作。

    3.3 Stream流的终止操作

    Stream流的终止操作后,可以从流中生成结果,其结果可以是任何不是流的值。比如forEach遍历结果、collect转换为其它型类型式。

    4.stream包的几个Stream接口

    java.util.stream包的几个Stream接口。Stream、IntStream、LongStream、DoubleStream接口都继承BaseStream。

    1. java.util.stream.BaseStream
    2. java.util.stream.Stream
    3. java.util.stream.IntStream
    4. java.util.stream.LongStream
    5. java.util.stream.DoubleStream

    三、Stream应用

    本例根据操作Stream的3个基本步骤,把函数分为3类,在逐个应用。

    1.应用Stream流的创建函数

    应用Stream流的创建方式,使用这些函数可以从数据源获取Stream流。

    1.1 操作场景

    操作场景,就是函数功能。

    (1)使用List获取Stream流。

    (2)使用Map获取Stream流。

    (3)使用List获取Stream流。

    (4)使用List获取Stream流。

    (5)使用Stream.of获取Stream流

    (6)使用Stream.Builder获取Stream流。

    (7)使用Stream.generate获取Stream流。

    (8)使用Stream.iterate获取Stream流。

    (9)使用Stream.concat合并两个流。

    (10)使用Stream.empty获取空流。

    1.2 操作实例

    操作实例,就是函数应用。

    1. /**
    2. * 1.1使用List获取Stream流
    3. */
    4. public static void f1_1() {
    5. // 1.获取数据(List)
    6. List list = getList();
    7. // 2.获取Stream流(使用List)
    8. Stream stream = list.stream();
    9. // 3.遍历Stream流
    10. stream.forEach(girlVo -> {
    11. System.out.println(girlVo.toString());
    12. });
    13. }
    14. /**
    15. * 1.2使用Map获取Stream流
    16. */
    17. public static void f1_2() {
    18. // 1.获取数据(Map)
    19. Map map = getMap();
    20. // 2.获取Stream流(使用Map)
    21. Stream> stream = map.entrySet().stream();
    22. // 3.遍历Stream流
    23. stream.forEach(girlVo -> System.out.println(girlVo.toString()));
    24. }
    25. /**
    26. * 1.3使用List获取Stream流
    27. */
    28. public static void f1_3() {
    29. // 1.获取数据(set)
    30. Set list = getSet();
    31. // 2.获取Stream流(使用set)
    32. Stream stream = list.stream();
    33. // 3.遍历Stream流
    34. stream.forEach(girlVo -> {
    35. System.out.println(girlVo.toString());
    36. });
    37. }
    38. /**
    39. * 1.4使用List获取Stream流
    40. */
    41. public static void f1_4() {
    42. // 1.获取数据(数组)
    43. String[] cityArray = new String[]{"厦门", "杭州", "苏州", "北京"};
    44. // 2.获取Stream流(使用数组)
    45. Stream stream = Arrays.stream(cityArray);
    46. // 3.遍历Stream流
    47. stream.forEach(System.out::println);
    48. }
    49. /**
    50. * 1.5使用Stream.of获取Stream流
    51. */
    52. public static void f1_5() {
    53. // 1.使用Stream.of获取Stream流(单个元素)
    54. Stream stream01 = Stream.of("杭州");
    55. // 2.使用Stream.of获取Stream流
    56. Stream stream02 = Stream.of("北京", "杭州", "厦门", "苏州");
    57. stream02.forEach(System.out::println);
    58. }
    59. /**
    60. * 1.6使用Stream.Builder获取Stream流
    61. */
    62. public static void f1_6() {
    63. // 1.创建Builder
    64. Stream.Builder builder = Stream.builder();
    65. // 2.添加元素
    66. builder.add("北京");
    67. builder.add("苏州");
    68. // 3.创建Stream
    69. Stream stream = builder.build();
    70. // 4.遍历Stream
    71. stream.forEach(System.out::println);
    72. }
    73. /**
    74. * 1.7使用Stream.generate获取Stream流
    75. */
    76. public static void f1_7() {
    77. Stream stream04 = Stream.generate(Math::random);
    78. stream04.forEach(num -> System.out.println("generate: " + num));
    79. }
    80. /**
    81. * 1.8使用Stream.iterate获取Stream流
    82. */
    83. public static void f1_8() {
    84. Stream stream05 = Stream.iterate(30L, ele -> (ele + 2));
    85. stream05.forEach(num -> System.out.println("iterate: " + num));
    86. }
    87. /**
    88. * 1.9 使用Stream.concat合并两个流
    89. */
    90. public static void f1_9() {
    91. // 1.使用Stream.of获取Stream流
    92. Stream stream0401 = Stream.of("北京", "杭州");
    93. Stream stream0402 = Stream.of("厦门", "苏州");
    94. // 2.使用Stream.concat合并两个流
    95. Stream stream04 = Stream.concat(stream0401, stream0402);
    96. stream04.forEach(num -> System.out.println("合并流: " + num));
    97. }
    98. /**
    99. * 1.10 使用Stream.empty获取空流
    100. */
    101. public static void f1_10() {
    102. // 1.使用Stream.empty获取空流
    103. Stream stream01 = Stream.empty();
    104. }
    105. 2.应用Stream流的中间操作函数

      应用Stream流的中间操作函数,使用这些函数对Stream流进行操作,操作的结果还是Stream流。

      2.1 操作场景

      操作场景,就是函数功能。

      (1)应用Stream的filter,做过滤筛选操作。

      (2)应用Stream的map,把Stream转换为Stream

      (3)应用Stream的mapToInt,把Stream转换为IntStream。

      (4)应用Stream的mapToLong,把Stream转换为LongStream。

      (5)应用Stream的mapToDouble,把Stream转换为DoubleStream。

      (6)应用Stream的flatMap,把List>转换为Stream

      (7)应用Stream的flatMapToInt,把List>转换为IntStream。

      (8)应用Stream的flatMapToLong,把List>转换为LongStream。

      (9)应用Stream的flatMapToDouble,把List>转换为DoubleStream。

      (10)应用Stream的distinct去重。

      (11)应用Stream的sorted排序。

      (12)应用Stream的sorted排序。

      (13)应用Stream的peek调试。

      (14)应用Stream的limit,限制数量。

      (15)应用Stream的skip,跳过指定个数元素。

      2.2 操作实例

      操作实例,就是函数应用。

      1. /**
      2. * 2.1 应用Stream的filter,做过滤筛选操作
      3. * 案例: 找出B罩杯,年龄最小的女孩.
      4. */
      5. public static void f2_1() {
      6. // 1.获取数据(List)
      7. List list = getList();
      8. // 2.获取Stream流(使用List)
      9. Stream stream = list.stream();
      10. // 3.Stream的filter的使用
      11. OptionalLong optionalLong = stream.filter(girlVo -> Objects.equals(
      12. girlVo.getCupSize(), "B"))
      13. .mapToLong(GirlVo::getAge).min();
      14. // 4.获取结果
      15. if (optionalLong.isPresent()) {
      16. System.out.println("B罩杯,年龄最小的女孩: " + optionalLong.getAsLong());
      17. }
      18. }
      19. /**
      20. * 2.2 应用Stream的map
      21. * 案例: 把Stream转换为Stream
      22. */
      23. public static void f2_2() {
      24. // 1.获取数据(List)
      25. List list = getList();
      26. // 2.获取Stream流(使用List)
      27. Stream stream = list.stream();
      28. // 3.Stream转换为Stream
      29. Stream objStream = stream.map(girlVo -> {
      30. Object obj = girlVo.getGirlName();
      31. return obj;
      32. });
      33. // 4.遍历结果
      34. objStream.forEach(obj -> {
      35. System.out.println("Girl的名称: " + obj.toString());
      36. });
      37. }
      38. /**
      39. * 2.3 应用Stream的mapToInt
      40. * 案例: 把Stream转换为IntStream
      41. */
      42. public static void f2_3() {
      43. // 1.获取数据(List)
      44. List list = getList();
      45. // 2.获取Stream流(使用List)
      46. Stream stream = list.stream();
      47. // 3.Stream转换为IntStream
      48. IntStream intStream = stream.mapToInt(girlVo -> {
      49. int girlId = Integer.parseInt(girlVo.getGirlId());
      50. return girlId;
      51. });
      52. // 4.遍历结果
      53. intStream.forEach(girlId -> {
      54. System.out.println("Girl的ID: " + girlId);
      55. });
      56. }
      57. /**
      58. * 2.4 应用Stream的mapToLong
      59. * 案例: 把Stream转换为LongStream
      60. */
      61. public static void f2_4() {
      62. // 1.获取数据(List)
      63. List list = getList();
      64. // 2.获取Stream流(使用List)
      65. Stream stream = list.stream();
      66. // 3.Stream转换为LongStream
      67. LongStream longStream = stream.mapToLong(girlVo -> {
      68. long girlId = girlVo.getAge();
      69. return girlId;
      70. });
      71. // 4.使用LongStream的average求平均值
      72. OptionalDouble opt = longStream.average();
      73. if (opt.isPresent()) {
      74. System.out.println("Girl的平均年龄: " + opt.getAsDouble());
      75. }
      76. }
      77. /**
      78. * 2.5 应用Stream的mapToDouble
      79. * 案例: 把Stream转换为DoubleStream
      80. */
      81. public static void f2_5() {
      82. // 1.获取数据(List)
      83. List list = getList();
      84. // 2.获取Stream流(使用List)
      85. Stream stream = list.stream();
      86. // 3.Stream转换为DoubleStream
      87. DoubleStream doubleStream = stream.mapToDouble(girlVo -> {
      88. double height = girlVo.getHeight();
      89. return height;
      90. });
      91. // 4.使用DoubleStream的max求最大值
      92. OptionalDouble opt = doubleStream.max();
      93. if (opt.isPresent()) {
      94. System.out.println("身高最高的girl身高: " + opt.getAsDouble());
      95. }
      96. }
      97. /**
      98. * 2.6 应用Stream的flatMap
      99. * 案例: 把List>转换为Stream
      100. */
      101. public static void f2_6() {
      102. // 1.获取数据(List>)
      103. List> list = getMultiList();
      104. // 2.List>转换为Stream
      105. Stream stream = list.stream().flatMap(mapper -> {
      106. return mapper.stream();
      107. });
      108. // 3.遍历结果
      109. stream.forEach(obj -> {
      110. System.out.println("遍历信息: " + obj.toString());
      111. });
      112. }
      113. /**
      114. * 2.7 应用Stream的flatMapToInt
      115. * 案例: 把List>转换为IntStream
      116. */
      117. public static void f2_7() {
      118. // 1.获取数据(List>)
      119. List> list = getMultiList();
      120. // 2.List>转换为IntStream
      121. IntStream stream = list.stream().flatMapToInt(mapper -> {
      122. Stream girlStream = mapper.stream();
      123. return girlStream.mapToInt(girl -> {
      124. return (int) girl.getAge();
      125. });
      126. });
      127. // 3.遍历结果
      128. stream.forEach(age -> {
      129. System.out.println("年龄: " + age);
      130. });
      131. }
      132. /**
      133. * 2.8 应用Stream的flatMapToLong
      134. * 案例: 把List>转换为LongStream
      135. * 相当于: 把List>循环遍历2次直接在Stream中完成
      136. */
      137. public static void f2_8() {
      138. // 1.获取数据(List>)
      139. List> list = getMultiList();
      140. // 2.List>转换为LongStream
      141. LongStream stream = list.stream().flatMapToLong(mapper -> {
      142. Stream girlStream = mapper.stream();
      143. return girlStream.mapToLong(girl -> Long.parseLong(girl.getGirlId()));
      144. });
      145. // 3.遍历结果
      146. stream.forEach(age -> {
      147. System.out.println("年龄: " + age);
      148. });
      149. }
      150. /**
      151. * 2.9 应用Stream的flatMapToDouble
      152. * 案例: 把List>转换为DoubleStream
      153. */
      154. public static void f2_9() {
      155. // 1.获取数据(List>)
      156. List> list = getMultiList();
      157. // 2.List>转换为LongStream
      158. DoubleStream stream = list.stream().flatMapToDouble(mapper -> {
      159. Stream girlStream = mapper.stream();
      160. // Lambda表达式写法
      161. return girlStream.mapToDouble(GirlVo::getHeight);
      162. });
      163. // 3.遍历结果
      164. stream.forEach(height -> {
      165. System.out.println("身高: " + height);
      166. });
      167. }
      168. /**
      169. * 2.10 应用Stream的distinct去重
      170. * 案例: 应用Stream的distinct去重
      171. * 原理: 去重根据Object.equals(Object)判断
      172. * Girl01是从写了equals(Object obj)和 hashCode(),去重效果才会生效
      173. */
      174. public static void f2_10() {
      175. // 1.获取数据(List)
      176. List list = getList01();
      177. // 2.获取Stream流(使用List)
      178. Stream stream01 = list.stream();
      179. // 3.使用distinct去重
      180. Stream stream02 = stream01.distinct();
      181. // 4.遍历结果
      182. stream02.forEach(Girl01 -> {
      183. System.out.println("Girl信息: " + Girl01);
      184. });
      185. }
      186. /**
      187. * 2.11 应用Stream的sorted排序
      188. * 案例: 应用Stream的sorted排序
      189. */
      190. public static void f2_11() {
      191. // 1.获取数据(List)
      192. List list = getList();
      193. // 2.获取Stream流(使用List)
      194. Stream stream01 = list.stream();
      195. // 3.使用sorted排序
      196. Stream stream02 = stream01.map(GirlVo::getAge).sorted();
      197. // 4.遍历结果
      198. stream02.forEach(girl -> {
      199. System.out.println("Girl年龄: " + girl);
      200. });
      201. }
      202. /**
      203. * 2.12 应用Stream的sorted排序
      204. * 案例: 应用Stream的sorted排序
      205. */
      206. public static void f2_12() {
      207. // 1.获取数据(List)
      208. List list = getList();
      209. // 2.获取Stream流(使用List)
      210. Stream stream01 = list.stream();
      211. // 3.使用sorted排序 int compare(T o1, T o2);o1-o2代表正序排序,o2-o1代表倒序排序
      212. Stream stream02 = stream01.sorted((girl01, girl02) -> {
      213. return (int) (girl01.getAge() - girl02.getAge());
      214. });
      215. // 4.遍历结果
      216. stream02.forEach(girl -> {
      217. System.out.println("Girl信息: " + girl);
      218. });
      219. }
      220. /**
      221. * 2.13 应用Stream的peek调试
      222. * 案例: 应用Stream的peek对流操作中的流水线进行调试
      223. */
      224. public static void f2_13() {
      225. // 1.获取数据(List)
      226. List list = getList();
      227. // 2.应用Stream的peek记录调试过程
      228. Stream stream01 = list.stream().peek(girlVo -> {
      229. System.out.println("首次peek: " + girlVo);
      230. }).filter(girlVo -> girlVo.getAge() > 25)
      231. .peek(girlVo -> {
      232. System.out.println("filter后peek: " + girlVo);
      233. }).sorted((girl01, girl02) -> {
      234. return (int) (girl01.getAge() - girl02.getAge());
      235. }).peek(girlVo -> {
      236. System.out.println("sorted后peek: " + girlVo);
      237. });
      238. // 3.遍历结果
      239. stream01.forEach(girl -> {
      240. System.out.println("forEach遍历girl信息: " + girl);
      241. });
      242. }
      243. /**
      244. * 2.14 应用Stream的limit,限制数量
      245. * 案例: 应用Stream的limit,限制数量
      246. */
      247. public static void f2_14() {
      248. // 1.获取数据(List)
      249. List list01 = getList();
      250. // 2.获取Stream流(使用List)
      251. Stream stream01 = list01.stream();
      252. // 3.应用Stream的limit
      253. List list0101 = stream01.limit(2).collect(Collectors.toList());
      254. }
      255. /**
      256. * 2.15 应用Stream的skip,跳过指定个数元素
      257. * 案例: 应用Stream的skip,跳过指定个数元素
      258. */
      259. public static void f2_15() {
      260. // 1.获取数据(List)
      261. List list02 = getList();
      262. // 2.获取Stream流(使用List)
      263. Stream stream02 = list02.stream();
      264. // 3.应用Stream的skip
      265. List list0201 = stream02.skip(2).collect(Collectors.toList());
      266. }
      267. 3.应用Stream流的终止操作函数

        应用Stream流的终止操作函数,使用这些函数对Stream流进行操作后,生成结果不是Stream流了,而是一个期待类型的结果值。

        3.1 操作场景

        操作场景,就是函数功能。

        (1)应用Stream的forEach和forEachOrdered遍历结果。

        (2)应用Stream的toArray将流转换为数组。

        (3)应用Stream的reduce,做累加操作。

        (4)应用Stream的collect,将流转换为集合。

        (5)应用Stream的collect,将流转换为连续字符串。

        (6)应用Stream的collect,将流转换为List集合。

        (7)应用Stream的collect,对流做分组操作,转换为Map>。

        (8)应用Stream的collect,对流做分组操作,转换为Map>>。

        (9)应用Stream的min,找到最小值。

        (10)应用Stream的max,找到最大值。

        (11)应用Stream的count,找到元素个数。

        (12)应用Stream的anyMatch,有一个匹配则true。

        (13)应用Stream的allMatch,全部匹配则true。

        (14)应用Stream的noneMatch,不存在则true。

        (15)应用Stream的findFirst,找到第一个元素。

        (16)应用Stream的findAny,找到任意一个元素。

        3.2 操作实例

        操作实例,就是函数应用。

        1. /**
        2. * 3.1 应用Stream的forEach遍历结果
        3. * 案例: 应用Stream的forEach和forEachOrdered
        4. */
        5. public static void f3_1() {
        6. // 1.1 获取数据(List)
        7. List list03 = getList();
        8. // 1.2 获取Stream流(使用List)
        9. Stream stream03 = list03.stream();
        10. // 1.3 使用forEach遍历结果
        11. stream03.forEach(girlVo -> System.out.println("girl信息: " + girlVo));
        12. // 2.1 获取数据(List)
        13. List list04 = getList();
        14. // 2.2 获取Stream流(使用List)
        15. Stream stream04 = list04.stream();
        16. // 2.3 使用forEachOrdered遍历结果
        17. stream04.forEachOrdered(girlVo -> System.out.println("girl信息Ordered: " + girlVo));
        18. }
        19. /**
        20. * 3.2 应用Stream的toArray
        21. * 案例: 应用Stream的toArray将流转换为数组
        22. */
        23. public static void f3_2() {
        24. // 1.1 获取数据(List)
        25. List list05 = getList();
        26. // 1.2 获取Stream流(使用List)
        27. Stream stream05 = list05.stream();
        28. // 1.3 应用toArray将Stream流转换为数组
        29. Object[] objs = stream05.toArray();
        30. // 2.1 获取数据(List)
        31. List list06 = getList();
        32. // 2.2 获取Stream流(使用List)
        33. Stream stream06 = list06.stream();
        34. // 2.3 应用toArray将Stream流转换为数组
        35. Object[] objs2 = stream06.toArray(GirlVo[]::new);
        36. }
        37. /**
        38. * 3.3 应用Stream的reduce
        39. * 案例: 应用Stream的reduce,做累加操作
        40. */
        41. public static void f3_3() {
        42. // 1.1 获取数据(List)
        43. List list01 = getList();
        44. // 1.2.获取Stream流(使用List)
        45. LongStream stream01 = list01.stream().mapToLong(GirlVo::getAge);
        46. // 1.3 应用reduce求和操作
        47. OptionalLong opt01 = stream01.reduce((a, b) -> a + b);
        48. if (opt01.isPresent()) {
        49. System.out.println("输出值: " + opt01.getAsLong());
        50. }
        51. // 2.1 获取数据(List)
        52. List list02 = getList();
        53. // 2.2.获取Stream流(使用List)
        54. LongStream stream02 = list02.stream().mapToLong(GirlVo::getAge);
        55. // 2.3 应用reduce求和操作
        56. long opt02 = stream02.reduce(100, (a, b) -> a + b);
        57. System.out.println("输出值: " + opt02);
        58. // 3.1 获取Stream流(Stream.of)
        59. Stream stream = Stream.of(100, 200, 300, 400);
        60. // 3.2 应用reduce求和操作
        61. Integer result = stream.reduce(0, Integer::sum, Integer::sum);
        62. System.out.println("result" + result);
        63. }
        64. /**
        65. * 3.4 应用Stream的collect
        66. * 案例: 应用Stream的collect,将流转换为集合
        67. */
        68. public static void f3_4() {
        69. // 1.获取Stream流(Stream.of)
        70. Stream stringStream0101 = Stream.of("北京", "杭州", "厦门", "苏州");
        71. // 2.应用Stream的collect,将流转换为集合
        72. List asList0101 = stringStream0101.collect(ArrayList::new, ArrayList::add,
        73. ArrayList::addAll);
        74. System.out.println("asList0101: " + asList0101);
        75. }
        76. /**
        77. * 3.5 应用Stream的collect
        78. * 案例: 应用Stream的collect,将流转换为连续字符串
        79. */
        80. public static void f3_5() {
        81. // 1.获取Stream流(Stream.of)
        82. Stream stringStream02 = Stream.of("北京,", "杭州,", "厦门,", "苏州,", "是不错的城市.");
        83. // 2.应用Stream的collect,将流转换为连续字符串
        84. String concat = stringStream02.collect(StringBuilder::new, StringBuilder::append,
        85. StringBuilder::append).toString();
        86. System.out.println("concat: " + concat);
        87. }
        88. /**
        89. * 3.6 应用Stream的collect
        90. * 案例: 应用Stream的collect,将流转换为List集合
        91. */
        92. public static void f3_6() {
        93. // 1.获取Stream流(Stream.of)
        94. Stream stringStream0201 = Stream.of("北京", "杭州", "郑州", "厦门", "苏州");
        95. // 2.应用Stream的collect,将流转换为List
        96. List asList0201 = stringStream0201.collect(Collectors.toList());
        97. System.out.println("asList0201: " + asList0201);
        98. }
        99. /**
        100. * 3.7 应用Stream的collect
        101. * 案例: 应用Stream的collect,对流做分组操作,转换为Map>
        102. */
        103. public static void f3_7() {
        104. // 1.获取Stream流(Stream.of)
        105. Stream girlStream0201 = getList().stream();
        106. // 2.应用Stream的collect,将流分组转换为Map>
        107. Map> girlByCupSize = girlStream0201.collect(Collectors.groupingBy(GirlVo::getCupSize));
        108. System.out.println("girlByCupSize: " + girlByCupSize);
        109. }
        110. /**
        111. * 3.8 应用Stream的collect
        112. * 案例: 应用Stream的collect,对流做分组操作,转换为Map>>
        113. */
        114. public static void f3_8() {
        115. // 1.获取Stream流(使用List)
        116. Stream girlStream0202 = getList().stream();
        117. // 2.应用Stream的collect,对流做分组操作,转换为Map>>
        118. Map>> girlByCupSizeAndAge
        119. = girlStream0202.collect(Collectors.groupingBy(GirlVo::getCupSize,
        120. Collectors.groupingBy(GirlVo::getAge)));
        121. System.out.println("peopleByCupSizeAndAge: " + girlByCupSizeAndAge);
        122. }
        123. /**
        124. * 3.9 应用Stream的min
        125. * 案例: 应用Stream的min,找到最小值
        126. */
        127. public static void f3_9() {
        128. // 1.获取Stream流(Stream.of)
        129. Stream stream01 = Stream.of(100L, 200L, 300L);
        130. // 2.应用Stream的min,求最小值
        131. Optional opt01 = stream01.min((o1, o2) -> (int) (o1 - o2));
        132. // 3.获取结果
        133. if (opt01.isPresent()) {
        134. System.out.println("opt01: " + opt01);
        135. }
        136. }
        137. /**
        138. * 3.10 应用Stream的max
        139. * 案例: 应用Stream的max,找到最大值
        140. */
        141. public static void f3_10() {
        142. // 1.获取Stream流(Stream.of)
        143. Stream stream02 = Stream.of(100L, 200L, 300L);
        144. // 2.应用Stream的max,求最小值
        145. Optional opt02 = stream02.max((o1, o2) -> (int) (o1 - o2));
        146. // 3.获取结果
        147. if (opt02.isPresent()) {
        148. System.out.println("opt02: " + opt02);
        149. }
        150. }
        151. /**
        152. * 3.11 应用Stream的count
        153. * 案例: 应用Stream的count,找到元素个数
        154. */
        155. public static void f3_11() {
        156. // 1.获取Stream流(Stream.of)
        157. Stream stream03 = Stream.of(100L, 200L, 300L);
        158. // 2.应用Stream的count,求元素个数
        159. long opt03 = stream03.count();
        160. // 3.打印结果
        161. System.out.println("opt03: " + opt03);
        162. }
        163. /**
        164. * 3.12 应用Stream的anyMatch
        165. * 案例: 应用Stream的anyMatch,有一个匹配则true
        166. */
        167. public static void f3_12() {
        168. // 1.获取Stream流(使用List)
        169. Stream girlStream01 = getList().stream();
        170. // 2.应用Stream的anyMatch,有一个匹配则true
        171. boolean result01 = girlStream01.anyMatch(girl -> Objects.equals(girl.getCupSize(), "B"));
        172. // 3.打印结果
        173. System.out.println("是否有B罩杯: " + result01);
        174. }
        175. /**
        176. * 3.13 应用Stream的allMatch
        177. * 案例: 应用Stream的allMatch,全部匹配则true
        178. */
        179. public static void f3_13() {
        180. // 1.获取Stream流(使用List)
        181. Stream girlStream02 = getList().stream();
        182. // 2.应用Stream的anyMatch,全部匹配则true
        183. boolean result02 = girlStream02.allMatch(girl -> Objects.equals(girl.getCupSize(), "B"));
        184. // 3.打印结果
        185. System.out.println("是否所有的都是B罩杯: " + result02);
        186. }
        187. /**
        188. * 3.14 应用Stream的noneMatch
        189. * 案例: 应用Stream的noneMatch,不存在则true
        190. */
        191. public static void f3_14() {
        192. // 1.获取Stream流(使用List)
        193. Stream girlStream03 = getList().stream();
        194. // 2.应用Stream的anyMatch,不存在则true
        195. boolean result03 = girlStream03.noneMatch(girl -> Objects.equals(girl.getCupSize(), "G"));
        196. // 3.打印结果
        197. System.out.println("是否所有的都是G罩杯: " + result03);
        198. }
        199. /**
        200. * 3.15 应用Stream的findFirst
        201. * 案例: 应用Stream的findFirst,找到第一个元素
        202. */
        203. public static void f3_15() {
        204. // 1.获取Stream流(使用List)
        205. Stream stringStream01 = Stream.of("北京", "杭州", "厦门", "苏州");
        206. // 2.应用Stream的findFirst,找到第一个元素
        207. Optional opt01 = stringStream01.findFirst();
        208. // 3.打印结果
        209. opt01.ifPresent(city -> System.out.println("第一个: " + city));
        210. }
        211. /**
        212. * 3.16 应用Stream的findAny
        213. * 案例: 应用Stream的findAny,找到任意一个元素
        214. */
        215. public static void f3_16() {
        216. // 1.获取Stream流(使用List)
        217. Stream stringStream02 = Stream.of("北京", "杭州", "郑州", "厦门", "苏州");
        218. // 2.应用Stream的findAny,找到任意一个元素
        219. Optional opt02 = stringStream02.findAny();
        220. // 3.打印结果
        221. opt02.ifPresent(city -> System.out.println("任意一个: " + city));
        222. }

        4.本例生成数据的函数和Java Bean对象

        测试验证需要数据,生成辅助类和方法。

        4.1 Java Bean对象

        Java Bean对象,包括GirlVo和Girl01,主要使用GirlVo。Girl01在做去重时使用到,因为重写了基类Object的equals(Object obj)和 hashCode()。

        (1)GirlVo

        1. @Data
        2. @NoArgsConstructor
        3. @AllArgsConstructor
        4. @Builder
        5. public class GirlVo {
        6. /**ID号*/
        7. String girlId;
        8. /**姓名*/
        9. String girlName;
        10. /**年龄*/
        11. long age;
        12. /**身高*/
        13. double height;
        14. /**罩杯*/
        15. String cupSize;
        16. }

        (2)Girl01

        1. @Data
        2. @NoArgsConstructor
        3. @AllArgsConstructor
        4. @Builder
        5. public class Girl01 {
        6. /**ID号*/
        7. String girlId;
        8. /**姓名*/
        9. String girlName;
        10. /**年龄*/
        11. long age;
        12. /**身高*/
        13. double height;
        14. /**罩杯*/
        15. String cupSize;
        16. @Override
        17. public boolean equals(Object obj) {
        18. if (this == obj) return true;
        19. if (obj == null || getClass() != obj.getClass()) return false;
        20. Girl01 var = (Girl01) obj;
        21. return (Objects.equals(this.girlId, var.girlId));
        22. }
        23. @Override
        24. public int hashCode() {
        25. return Objects.hash(girlId);
        26. }
        27. }

        4.2 生成数据的函数

        生成数据的函数,包括以下几个。

        (1)获取List数据,在List中存放GirlVo对象。

        (2)获取Map数据,在Map中存放(key,value)对应(girlId,GirlVo)。

        (3)获取Set数据,在Set中存放GirlVo对象。

        (4)获取List>。

        (5)获取List数据,在List中存放Girl01对象。

        1. /**
        2. * 获取List数据,在List中存放GirlVo对象
        3. */
        4. public static List getList() {
        5. List list = new ArrayList<>();
        6. GirlVo girl01 = GirlVo.builder().girlId("1001").girlName("张一").age(27).height(169).cupSize("F").build();
        7. GirlVo girl02 = GirlVo.builder().girlId("1002").girlName("王二").age(29).height(175).cupSize("B").build();
        8. GirlVo girl03 = GirlVo.builder().girlId("1003").girlName("刘五").age(24).height(160).cupSize("B").build();
        9. GirlVo girl04 = GirlVo.builder().girlId("1004").girlName("陈六").age(21).height(168).cupSize("C").build();
        10. GirlVo girl05 = GirlVo.builder().girlId("1005").girlName("赵七").age(25).height(169).cupSize("C").build();
        11. GirlVo girl06 = GirlVo.builder().girlId("1006").girlName("张八").age(26).height(165).cupSize("A").build();
        12. list.add(girl01);
        13. list.add(girl02);
        14. list.add(girl03);
        15. list.add(girl04);
        16. list.add(girl05);
        17. list.add(girl06);
        18. return list;
        19. }
        20. /**
        21. * 获取Map数据,在Map中存放(key,value)对应(girlId,GirlVo)
        22. */
        23. public static Map getMap() {
        24. Map map = new HashMap<>();
        25. List list = getList();
        26. Stream stream = list.stream();
        27. stream.forEach(girlVo -> {
        28. map.put(girlVo.getGirlId(), girlVo);
        29. });
        30. return map;
        31. }
        32. /**
        33. * 获取Set数据,在Set中存放GirlVo对象
        34. */
        35. public static Set getSet() {
        36. Set set = new HashSet<>();
        37. List list = getList();
        38. Stream stream = list.stream();
        39. stream.forEach(girlVo -> {
        40. set.add(girlVo);
        41. });
        42. return set;
        43. }
        44. /**
        45. * 获取List>
        46. */
        47. public static List> getMultiList() {
        48. List list01 = new ArrayList<>();
        49. List list02 = new ArrayList<>();
        50. List> list = new ArrayList<>();
        51. GirlVo girl01 = GirlVo.builder().girlId("1001").girlName("张一").age(27).height(169).cupSize("F").build();
        52. GirlVo girl02 = GirlVo.builder().girlId("1002").girlName("王二").age(29).height(175).cupSize("B").build();
        53. GirlVo girl03 = GirlVo.builder().girlId("1003").girlName("刘五").age(24).height(160).cupSize("B").build();
        54. GirlVo girl04 = GirlVo.builder().girlId("1004").girlName("陈六").age(21).height(168).cupSize("C").build();
        55. GirlVo girl05 = GirlVo.builder().girlId("1005").girlName("赵七").age(25).height(169).cupSize("C").build();
        56. GirlVo girl06 = GirlVo.builder().girlId("1006").girlName("张八").age(26).height(165).cupSize("A").build();
        57. list01.add(girl01);
        58. list01.add(girl02);
        59. list01.add(girl03);
        60. list02.add(girl04);
        61. list02.add(girl05);
        62. list02.add(girl06);
        63. list.add(list01);
        64. list.add(list02);
        65. return list;
        66. }
        67. /**
        68. * 获取List数据,在List中存放Girl01对象
        69. * Girl01是重写了equals(Object obj)和 hashCode()
        70. * 在使用distinct时去重根据重写规则判断
        71. */
        72. public static List getList01() {
        73. List list = new ArrayList<>();
        74. Girl01 girl01 = Girl01.builder().girlId("1001").girlName("张一").age(27).height(169).cupSize("F").build();
        75. Girl01 girl02 = Girl01.builder().girlId("1002").girlName("王二").age(29).height(175).cupSize("B").build();
        76. Girl01 girl03 = Girl01.builder().girlId("1003").girlName("刘五").age(24).height(160).cupSize("B").build();
        77. Girl01 girl04 = Girl01.builder().girlId("1004").girlName("陈六").age(21).height(168).cupSize("C").build();
        78. Girl01 girl05 = Girl01.builder().girlId("1005").girlName("赵七").age(25).height(169).cupSize("C").build();
        79. Girl01 girl06 = Girl01.builder().girlId("1001").girlName("张一").age(27).height(169).cupSize("F").build();
        80. list.add(girl01);
        81. list.add(girl02);
        82. list.add(girl03);
        83. list.add(girl04);
        84. list.add(girl05);
        85. list.add(girl06);
        86. return list;
        87. }

        四、小结

        在研究API时,训练是一方面。归纳和分类有助于理解整体思路以及API应用场景。

        以上,感谢。

        2022年8月21日

      268. 相关阅读:
        网络编程 day05 (linux )数据库 sqlite3 的下载 与使用命令,和在程序中运用sqlite3
        Unity3D 基础——使用 Vector3.Lerp 实现缓动效果
        Android Studio导入aosp源码
        安卓期末大作业——日记APP
        cookie机制 + java 案例
        【Ubuntu】Anaconda的安装和使用
        数字示波器verilog设计实现
        【强化学习论文合集】十.2018智能体和多智能体系统国际联合会议论文(AAMAS2018)
        【linux基础(六)】Linux中的开发工具(中)--gcc/g++
        串口转以太网产品选型指南
      269. 原文地址:https://blog.csdn.net/zhangbeizhen18/article/details/126455427