当前位置:   article > 正文

Java中的Stream流

Java中的Stream流

一、介绍

1. Stream流的作用

结合了Lambda表达式,简化集合、数组的操作。

2. Stream流的使用步骤

①先得到一条Stream流,并把数据放上去;

获取方式方法名说明
单列集合default Stream<E> stream()Collection中的默认方法
双列集合无法直接使用stream流
数组public static <T> Stream<T> stream(T[] array)Arrays工具类中的静态方法
一堆零散数据public static <T> Stream<T> of(T…values)Stream接口中的静态方法
(1)单列集合:
  1. import java.util.ArrayList;
  2. import java.util.Collections;
  3. import java.util.function.Consumer;
  4. import java.util.stream.Stream;
  5. public class StreamDemo2 {
  6. public static void main(String[] args) {
  7. // 1. 单列集合获取Stream流
  8. ArrayList<String> list = new ArrayList<>();
  9. Collections.addAll(list, "a", "b", "c", "d", "e");
  10. /*// 获取一条流水线,并把集合中的数据放到流水线上
  11. Stream<String> stream1 = list.stream();
  12. // 使用终结方法打印一条流水线上的所有数据
  13. stream1.forEach(new Consumer<String>() {
  14. @Override
  15. public void accept(String s) {
  16. // s:依次表示流水线上的每一个数据
  17. System.out.println(s);
  18. }
  19. });*/
  20. // 链式编程
  21. list.stream().forEach(s -> System.out.println(s));
  22. }
  23. }

(2)双列集合
  1. import java.util.HashMap;
  2. public class StreamDemo3 {
  3. public static void main(String[] args) {
  4. // 双列集合
  5. // 1. 创建双列集合
  6. HashMap<String, Integer> hm = new HashMap<>();
  7. // 2. 添加数据
  8. hm.put("aaa", 111);
  9. hm.put("bbb", 222);
  10. hm.put("ccc", 333);
  11. hm.put("ddd", 444);
  12. hm.put("eee", 555);
  13. // 3. 第一种方式 获取stream流
  14. hm.keySet().stream().forEach(s -> System.out.println(s));
  15. // 4. 第二种方式 获取stream流
  16. hm.entrySet().stream().forEach(s -> System.out.println(s));
  17. }
  18. }

(3)数组
  1. import java.util.Arrays;
  2. import java.util.stream.Stream;
  3. public class StreamDemo4 {
  4. public static void main(String[] args) {
  5. // 数组获取stream流
  6. // 1. 创建数组
  7. int[] arr1 = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
  8. String[] arr2 = {"a", "b", "c"};
  9. // 2. 获取stream流
  10. Arrays.stream(arr1).forEach(s -> System.out.println(s));
  11. System.out.println("----------------------------------");
  12. Arrays.stream(arr2).forEach(s -> System.out.println(s));
  13. // 注意:
  14. // Stream接口中静态方法of的细节
  15. // 方法的形参是一个可变参数,可以传递一堆零散的数据,也可以传递数组
  16. // 但是数组必须是引用数据类型的,如果传递基本数据类型,是会把整个数组当作一个元素,放到stream当中。。
  17. Stream.of(arr1).forEach(s -> System.out.println(s)); // [I@214c265e
  18. Stream.of(arr2).forEach(s -> System.out.print(s + " ")); // a b c
  19. }
  20. }

(4)一堆零散数据
  1. import java.util.stream.Stream;
  2. public class StreamDemo5 {
  3. public static void main(String[] args) {
  4. // 一堆零散数据获取stream流
  5. Stream.of(1, 2, 3, 4, 5).forEach(s -> System.out.println(s));
  6. Stream.of("a", "b", "c", "d", "e").forEach(s -> System.out.println(s));
  7. }
  8. }

②利用中间方法对流水线上的数据进行各种操作;

注意1:中间方法,返回新的Stream流,原来的Stream流只能使用一次,建议使用链式编程

注意2:修改Stream流中的数据,不会影响原来集合或者数组中的数据

名称说明
Stream<T> filter(Predicate<? super<T> predicate)过滤
Stream<T> limit(long maxSize)获取前几个元素
Stream<T> skip(long n)跳过前几个元素
Stream<T> distinct()元素去重,依赖(hashCode和equals方法)
static<T> Stream<T> concat(Stream a, Stream b)合并a和b两个流为一个流
Stream<R> map(Function<T, R> mapper)转换流中的数据类型
  1. import java.util.ArrayList;
  2. import java.util.Collections;
  3. import java.util.stream.Stream;
  4. public class StreamDemo6 {
  5. public static void main(String[] args) {
  6. ArrayList<String> list = new ArrayList<>();
  7. Collections.addAll(list, "张无忌", "张无忌", "张无忌", "周芷若", "赵敏", "张强", "张三丰");
  8. // 1. fliter 过滤 把以”张“开头的留下,其余数据过滤不要
  9. /*list.stream().filter(new Predicate<String>() {
  10. @Override
  11. public boolean test(String s) {
  12. // 如果返回值为true,表示当前数据留下
  13. // 如果返回真为false,表示当前数据舍弃不要
  14. return s.startsWith("张");
  15. }
  16. }).forEach(s -> System.out.println(s));*/
  17. list.stream().filter(s -> s.startsWith("张")).forEach(s -> System.out.println(s));
  18. System.out.println("------------------------------");
  19. System.out.println(list); // 注意:修改Stream流中的数据,不会影响原理集合或者数组中的数据
  20. System.out.println("------------------------------");
  21. /*Stream<String> stream1 = list.stream().filter(s -> s.startsWith("张"));
  22. Stream<String> stream2 = stream1.filter(s -> s.length() == 3);
  23. stream2.forEach(s -> System.out.println(s));
  24. Stream<String> stream3 = stream1.filter(s -> s.length() == 3); // java.lang.IllegalStateException*/
  25. // 2. limit 获取前几个元素
  26. list.stream().limit(3).forEach(s -> System.out.println(s));
  27. System.out.println("------------------------------");
  28. // 3. skip 跳过前几个元素
  29. list.stream().skip(3).forEach(s -> System.out.println(s));
  30. System.out.println("------------------------------");
  31. // 4. distinct 元素去重
  32. list.stream().distinct().forEach(s -> System.out.println(s));
  33. System.out.println("------------------------------");
  34. // 5. concat 合并a和b两个流为一个流
  35. ArrayList<String> list2 = new ArrayList<>();
  36. Collections.addAll(list2, "周芷若", "赵六");
  37. Stream.concat(list.stream(), list2.stream()).forEach(s -> System.out.println(s));
  38. System.out.println("------------------------------");
  39. // 6. map 转换流中的数据类型
  40. ArrayList<String> list3 = new ArrayList<>();
  41. Collections.addAll(list3, "张无忌-15", "周芷若-14", "赵敏-13", "张强-20", "张三丰-100", "张翠山-40", "张良-35");
  42. // 只获取里面的年龄并进行打印
  43. // 当map方法执行完毕后,流上的数据就变成了整数
  44. // 所以再下面的foreach当中,s一次表示流里面的每一个数据,这个数据现在就是整数了
  45. /*list3.stream().map(new Function<String, Object>() {
  46. @Override
  47. public Object apply(String s) {
  48. String[] arr = s.split("-");
  49. String ageString = arr[1];
  50. int age = Integer.parseInt(ageString);
  51. return age;
  52. }
  53. }).forEach(s -> System.out.println(s));
  54. System.out.println("------------------------------");*/
  55. list3.stream()
  56. .map(s -> Integer.parseInt(s.split("-")[1]))
  57. .forEach(s -> System.out.println(s));
  58. }
  59. }

③使用终结方法对流水线上的数据进行操作

名称说明
void forEach(Consumer action)遍历
long count()统计
toArray()收集流中的数据,放到数组
collect(Collecctor collector)收集流中的数据,放到集合
  1. import java.util.*;
  2. import java.util.function.Function;
  3. import java.util.function.IntFunction;
  4. import java.util.stream.Collectors;
  5. public class StreamDemo7 {
  6. public static void main(String[] args) {
  7. ArrayList<String> list = new ArrayList<>();
  8. Collections.addAll(list, "张无忌", "周芷若", "赵敏", "张强", "张三丰");
  9. // 1. forEach 遍历
  10. // Consumer的泛型:表示流中数据的类型
  11. // accept方法的形参s:依次表示流里面的每一个数据
  12. // 方法体:对每一个数据的处理操作(打印)
  13. /* list.stream().forEach(new Consumer<String>() {
  14. @Override
  15. public void accept(String s) {
  16. System.out.println(s);
  17. }
  18. });*/
  19. list.stream().forEach(s -> System.out.println(s));
  20. System.out.println("--------------------------");
  21. // 2. count 统计
  22. long count = list.stream().count();
  23. System.out.println(count);
  24. System.out.println("--------------------------");
  25. // 3. toArray 收集流中的数据放到数组中
  26. Object[] arr1 = list.stream().toArray();
  27. System.out.println(Arrays.toString(arr1));
  28. System.out.println("--------------------------");
  29. // IntFunction的泛型:具体类型的数组
  30. // apply的形参:流中的数据的个数,要跟数组的长度保持一致
  31. // apply方法的返回值:具体类型的数组
  32. // 方法体:就是创建数组
  33. // toArray方法的参数的作用:负责创建一个指定类型的数组
  34. // toArray方法的底层:会依次得到流里面的每一个数据,并把数据放到数组当中
  35. // toArray方法的返回值:是一个装着流里面所有数据的数组
  36. /* String[] arr2 = list.stream().toArray(new IntFunction<String[]>() {
  37. @Override
  38. public String[] apply(int value) {
  39. return new String[value];
  40. }
  41. });
  42. System.out.println(Arrays.toString(arr2));
  43. System.out.println("--------------------------");*/
  44. String[] arr3 = list.stream().toArray(value -> new String[value]);
  45. System.out.println(Arrays.toString(arr3));
  46. System.out.println("--------------------------");
  47. // 4. 收集到List集合当中
  48. // 需求:把所有的男性收集起来
  49. ArrayList<String> list2 = new ArrayList<>();
  50. Collections.addAll(list2, "张无忌-男-15", "周芷若-女-14", "赵敏-女-13", "张强-男-20", "张三丰-男-100", "张翠山-男-40", "张良-男-35");
  51. List<String> newList = list2.stream()
  52. .filter(s -> "男".equals(s.split("-")[1]))
  53. .collect(Collectors.toList());
  54. System.out.println(newList);
  55. System.out.println("--------------------------");
  56. // 4. 收集到Set集合当中
  57. // 需求:把所有的男性收集起来
  58. Set<String> newSet = list2.stream().filter(s -> "男".equals(s.split("-")[1]))
  59. .collect(Collectors.toSet()); // 会自动去重
  60. System.out.println(newSet);
  61. System.out.println("--------------------------");
  62. // 4. 收集到Map集合当中
  63. // 谁作为键,谁作为值。把所有的男性收集起来
  64. // 键:姓名 值:年龄
  65. // 注意点:如果我们要收集数据到Map当中,键是不能重复的
  66. /* Map<String, Integer> newMap = list2.stream()
  67. .filter(s -> "男".equals(s.split("-")[1]))
  68. *//*
  69. toMap:参数一:键的生成规则。参数二:值的生成规则
  70. 参数一:Function泛型一:表示流中每一个数据的类型
  71. 泛型二:表示Map集合中键的数据类型
  72. 方法apply形参:依次表示流里面的每一个数据
  73. 方法体:生成键的代码
  74. 返回值:已经生成的键
  75. 参数二:Function泛型一:表示流中每一个数据的类型
  76. 泛型二:表示Map集合中值的数据类型
  77. 方法apply形参:依次表示流里面的每一个数据
  78. 方法体:生成值的代码
  79. 返回值:已经生成的值
  80. *//*
  81. .collect(Collectors.toMap(new Function<String, String>() {
  82. @Override
  83. public String apply(String s) {
  84. return s.split("-")[0]; // 姓名
  85. }
  86. },
  87. new Function<String, Integer>() {
  88. @Override
  89. public Integer apply(String s) {
  90. return Integer.parseInt(s.split("-")[2]);
  91. }
  92. }));
  93. System.out.println(newMap);
  94. System.out.println("--------------------------");*/
  95. // lambda表达式
  96. Map<String, Integer> map2 = list2.stream()
  97. .filter(s -> "男".equals(s.split("-")[1]))
  98. .collect(Collectors.toMap(
  99. s -> s.split("-")[0]
  100. ,
  101. s -> Integer.parseInt(s.split("-")[2])
  102. ));
  103. System.out.println(map2);
  104. }
  105. }

二、案例分析

1. 要求:按照下面的要求完成集合的创建和遍历。

①把所有以“张”开头的元素存储到新集合中;

②把“张”开头的,长度为3的元素再存储到新集合中;

③遍历打印最终结果。

  1. import java.util.ArrayList;
  2. public class StreamDemo1 {
  3. public static void main(String[] args) {
  4. ArrayList<String> list = new ArrayList<>();
  5. list.add("张无忌");
  6. list.add("周芷若");
  7. list.add("赵敏");
  8. list.add("张强");
  9. list.add("张三丰");
  10. list.stream().filter(name -> name.startsWith("张")).filter(name -> name.length() == 3).forEach(name -> System.out.println(name));
  11. // 张无忌
  12. // 张三丰
  13. }
  14. }

2.  数据过滤

        定义一个集合,并添加一些数据1,2,3,4,5,6,7,8,9,10。过滤奇数,只留下偶数,并将结果保存起来。

  1. import java.util.ArrayList;
  2. import java.util.Collections;
  3. import java.util.List;
  4. import java.util.stream.Collectors;
  5. public class StreamDemo8 {
  6. public static void main(String[] args) {
  7. /*
  8. 定义一个集合,并添加一些数据1,2,3,4,5,6,7,8,9,10。
  9. 过滤奇数,只留下偶数,并将结果保存起来。
  10. */
  11. // 1. 定义一个集合
  12. ArrayList<Integer> list = new ArrayList<>();
  13. // 2. 添加一些数据
  14. Collections.addAll(list, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10);
  15. // 3. 过滤奇数,只留下偶数
  16. // 进行判断,如果是偶数,返回true保留
  17. List<Integer> newList = list.stream()
  18. .filter(n -> n % 2 == 0)
  19. .collect(Collectors.toList());
  20. // 4. 打印集合
  21. System.out.println(newList);
  22. }
  23. }

3. 数据操作

        创建一个ArrayList集合,并添加以下字符串,字符串中前面是姓名,后面是年龄。”zhangsan, 23", "lisi, 24", "wangwu, 25"。保留年龄大于等于24岁的人,并将结果收到到Map集合中,姓名为键,年龄为值。

  1. import java.util.ArrayList;
  2. import java.util.Map;
  3. import java.util.stream.Collectors;
  4. public class StreamDemo9 {
  5. public static void main(String[] args) {
  6. /*
  7. 创建一个ArrayList集合,并添加以下字符串,字符串中前面是姓名,
  8. 后面是年龄。”zhangsan, 23", "lisi, 24", "wangwu, 25"。
  9. 保留年龄大于等于24岁的人,并将结果收到到Map集合中,
  10. 姓名为键,年龄为值。
  11. */
  12. // 1. 创建一个ArrayList集合
  13. ArrayList<String> list = new ArrayList<>();
  14. // 2. 添加以下字符串
  15. list.add("zhangsan, 23");
  16. list.add("lisi, 24");
  17. list.add("wangwu, 25");
  18. // 3. 保留年龄大于等于24岁的人
  19. Map<String, Integer> map = list.stream()
  20. .filter(s -> Integer.parseInt(s.split(", ")[1]) >= 24)
  21. .collect(Collectors.toMap(
  22. s -> s.split(", ")[0],
  23. s -> Integer.parseInt(s.split(", ")[1])));
  24. System.out.println(map);
  25. }
  26. }

4. 数据操作

        现有两个ArrayList集合,第一个集合:存储6名男演员的名字和年龄。第二个集合:存储6名女演员的名字和年龄。姓名和年龄中间用逗号隔开。比如,张三,23。

        要求完成下面的操作:①男演员只要名字为3个字的前两个人;②女演员只要姓杨的,并且不要第一个;③把过滤后的男演员姓名和女演员姓名合并到一起;④将上一步的演员信息封装成Actor对象;⑤将所有的演员对象都保存到List集合中。

备注:演员类Actor,属性只有一个:name,age

  1. import java.util.ArrayList;
  2. import java.util.Collections;
  3. import java.util.List;
  4. import java.util.function.Function;
  5. import java.util.stream.Collectors;
  6. import java.util.stream.Stream;
  7. public class StreamDemo10 {
  8. public static void main(String[] args) {
  9. /*
  10. 现有两个ArrayList集合,第一个集合:存储6名男演员的名字和年龄。
  11. 第二个集合:存储6名女演员的名字和年龄。姓名和年龄中间用逗号隔开。比如,张三,23。
  12. 要求完成下面的操作:①男演员只要名字为3个字的前两个人;
  13. ②女演员只要姓杨的,并且不要第一个;
  14. ③把过滤后的男演员姓名和女演员姓名合并到一起;
  15. ④将上一步的演员信息封装成Actor对象;⑤将所有的演员对象都保存到List集合中。
  16. 备注:演员类Actor,属性只有一个:name,age
  17. */
  18. // 1. 创建两个ArrayList集合
  19. ArrayList<String> manList = new ArrayList<>();
  20. ArrayList<String> womenList = new ArrayList<>();
  21. // 2. 添加数据
  22. Collections.addAll(manList, "小小蔡, 24", "小小叶, 23", "小小刘, 22", "小吴, 25", "小小谷, 23", "小李, 26");
  23. Collections.addAll(womenList, "杨小甜, 23", "杨小小, 21", "杨小鞠, 22", "小单, 24", "刘小陈, 22", "小小曲, 23");
  24. // 3. 男演员只要名字为3个字的前两个人
  25. Stream<String> stream1 = manList.stream()
  26. .filter(s -> s.split(", ")[0].length() == 3)
  27. .limit(2);
  28. // 4. 女演员只要姓杨的,并且不要第一个
  29. Stream<String> stream2 = womenList.stream()
  30. .filter(s -> s.split(", ")[0].startsWith("杨"))
  31. .skip(1);
  32. // 5. 把过滤后的男演员姓名和女演员姓名合并到一起
  33. // 6. 将上一步的演员信息封装成Actor对象(类型转换)
  34. /*Stream.concat(stream1, stream2).map(new Function<String, Actor>() {
  35. @Override
  36. public Actor apply(String s) {
  37. String name = s.split(", ")[0];
  38. int age = Integer.parseInt(s.split(", ")[1]);
  39. return new Actor(name, age);
  40. }
  41. }).forEach(s -> System.out.println(s));*/
  42. List<Actor> list = Stream.concat(stream1, stream2)
  43. .map(s -> new Actor(s.split(", ")[0], Integer.parseInt(s.split(", ")[1])))
  44. .collect(Collectors.toList());
  45. System.out.println(list);
  46. }
  47. }

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/Gausst松鼠会/article/detail/320299
推荐阅读
相关标签
  

闽ICP备14008679号