28.Stream流

Stream流

    • 1. 概述
    • 2. 方法
      • 2.1 开始生成方法
        • 2.1.1 概述
        • 2.1.2 方法
        • 2.1.3 代码示例
      • 2.2 中间操作方法
        • 2.2.1 概述
        • 2.2.2 方法
        • 2.2.3 代码示例
      • 2.3 终结操作方法
        • 2.3.1 概述
        • 2.3.2 方法
        • 2.3.3 代码示例
      • 2.4 收集操作方法
        • 2.4.1 概述
        • 2.4.2 方法
        • 2.4.3 代码示例
    • 3. 代码示例1
    • 4. 代码示例2
    • 5. 代码示例3
    • 6. 注意事项

1. 概述

Stream流是Java 8引入的一种新的数据处理方式,它可以用来处理集合(包括单列集合和双列集合)和数组中的数据。它提供了一种优雅、声明式的方式来对数据进行操作和处理,简化了对集合和数组的遍历、过滤、映射、排序等操作。

Stream流可以被认为是一种高级版本的迭代器。

  • 与传统的集合迭代器相比,Stream流具有以下特点
  1. Stream流不会对原有的数据集合进行修改,而是通过生成一个新的Stream流来进行操作。这种特性称为“惰性求值”,也就是说在对Stream流的操作时,并不会立即执行,只有在终止操作(如forEachcollect等)被调用时才会真正执行计算过程。

  2. Stream流支持并发操作,可以使用并行流来进行高效的多线程处理。通过并行化操作,可以极大地提高处理大数据集的效率。

  • Stream流的使用步骤

    1. 创建Stream流

    可以通过集合类的stream()方法、数组的stream()方法,或者使用Stream.of()方法来创建。

    1. 进行一系列中间操作

    通过调用Stream流的方法来对数据进行过滤、映射、排序等操作,这些操作会返回一个新的Stream流。

    1. 执行终止操作

    使用终止操作来触发对Stream流的计算。常见的终止操作包括forEach(遍历每个元素执行特定的操作)、collect(将元素收集到一个结果容器中)、reduce(归约操作,将多个元素合并为一个结果)等等。

  • 代码示例
    按照下面的要求完成集合的创建和遍历

    “张三丰”,“张无忌”,“张翠山”,“王二麻子”,“张良”,“谢广坤”

    • 创建一个集合,存储多个字符串元素

    • 把集合中所有以"张"开头的元素存储到一个新的集合

    • 把"张"开头的集合中的长度为3的元素存储到一个新的集合

    • 遍历上一步得到的集合

    package text.text02;import java.util.ArrayList;
    import java.util.Collections;
    import java.util.function.Consumer;/*初爽Stream流
    按照下面的要求完成集合的创建和遍历
    "张三丰","张无忌","张翠山","王二麻子","张良","谢广坤"
    - 创建一个集合,存储多个字符串元素
    - 把集合中所有以"张"开头的元素存储到一个新的集合
    - 把"张"开头的集合中的长度为3的元素存储到一个新的集合
    - 遍历上一步得到的集合*/
    public class text62 {public static void main(String[] args) {//未使用Stream流System.out.println("未使用Stream流:");method1();//使用了Stream流System.out.println("使用了Stream流:");method2();}//使用了Stream流private static void method2() {//创建集合并添加字符串元素ArrayList<String> list = new ArrayList<>();Collections.addAll(list, "张三丰", "张无忌", "张翠山", "王二麻子", "张良", "谢广坤");list.stream().filter(name -> name.startsWith("张")).filter(name -> name.length() == 3).forEach(new Consumer<String>() {@Overridepublic void accept(String name) {System.out.print(name + " ");}});}//未使用Stream流public static void method1() {//创建集合并添加字符串元素ArrayList<String> list = new ArrayList<>();Collections.addAll(list, "张三丰", "张无忌", "张翠山", "王二麻子", "张良", "谢广坤");//遍历集合获取以“张”开头的元素,并存在新的集合中ArrayList<String> list1 = new ArrayList<>();for (String name : list) {if (name.startsWith("张")) {list1.add(name);}}System.out.println("所有以\"张\"开头的元素存储到一个新的集合:" + list1);        //[张三丰, 张无忌, 张翠山, 张良]//把"张"开头的集合中的长度为3的元素存储到一个新的集合ArrayList<String> list2 = new ArrayList<>();for (String name : list1) {if (name.length() == 3) {list2.add(name);}}System.out.println("把\"张\"开头的集合中的长度为3的元素存储到一个新的集合:" + list2);  //[张三丰, 张无忌, 张翠山]}
    }
    
  • 输出结果

    • 未使用Stream流
      在这里插入图片描述

    • 使用了Stream流
      在这里插入图片描述

2. 方法

2.1 开始生成方法

2.1.1 概述

Stream流开始生成方法是指用于创建和获取Stream流的一些方法。在Java中,Stream是一种处理数据集合的抽象概念,它提供了丰富的数据操作和处理功能。

为了使用Stream,我们需要首先生成或获取到一个Stream流对象。

  • 生成Stream流的方式

    • Collection体系集合

      使用默认方法stream()生成流, default Stream stream()

    • Map体系集合

      把Map转成Set集合,间接的生成流

    • 数组

      通过Arrays中的静态方法stream生成流

    • 同种数据类型的多个数据

      通过Stream接口的静态方法of(T… values)生成流

2.1.2 方法
获取方式方法名说明
单列集合default Streamstream()Collection中的默认方法
双列集合无法直接使用stream流
数组public static Stream stream(T[] array)Arrays工具类中的静态方法
-堆零散数据public staticStream of(T… values)Stream接口中的静态方法

细节:

  1. 单列集合:default Stream<E> stream(),此方法是Collection接口中的默认方法,用于将单列集合(如List、Set)转换为Stream流。

    例如:

    List<String> list = Arrays.asList("A", "B", "C");
    Stream<String> stream = list.stream();
    
  2. 双列集合:目前没有直接使用stream()方法将双列集合(如Map)转换为Stream流的方式。但是可以通过entrySet().stream()keySet().stream()等方式间接获得Stream流,以对双列集合进行操作。

  3. 数组:public static <T> Stream<T> stream(T[] array),此方法是Arrays工具类中的静态方法,用于将数组转换为Stream流。

    例如:

    String[] array = {"A", "B", "C"};
    Stream<String> stream = Arrays.stream(array);
    
  4. 散零数据:public static <T> Stream<T> of(T... values),此方法是Stream接口中的静态方法,用于将一系列散零的数据转换为Stream流。

    例如:

    Stream<String> stream = Stream.of("A", "B", "C");
    
2.1.3 代码示例
  • 代码示例1:单列集合

    package text.text02;import java.util.ArrayList;
    import java.util.Collections;
    import java.util.function.Consumer;
    import java.util.stream.Stream;/*生成方法:单列集合    | default Stream<E>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接口中的静态方法   |*/
    public class text63 {public static void main(String[] args) {//完整模式System.out.println("完整模式:");method1();      //aaa  bbb  ccc  ddd  eee  fff  ggg  hhh  iii  jjj  kkkSystem.out.println();//简写模式System.out.println("简写模式:");method2();     //aaa  bbb  ccc  ddd  eee  fff  ggg  hhh  iii  jjj  kkk}//简写模式private static void method2() {//创建单列集合ArrayList<String> list = new ArrayList<>();//添加数据Collections.addAll(list, "aaa", "bbb", "ccc", "ddd", "eee", "fff", "ggg", "hhh", "iii", "jjj", "kkk");//创建Stream流并输出list.stream().forEach(s -> System.out.print(s + "  "));}public static void method1() {//创建单列集合ArrayList<String> list = new ArrayList<>();//添加数据Collections.addAll(list, "aaa", "bbb", "ccc", "ddd", "eee", "fff", "ggg", "hhh", "iii", "jjj", "kkk");//创建Stream流Stream<String> stream = list.stream();//输出数据stream.forEach(new Consumer<String>() {@Overridepublic void accept(String s) {System.out.print(s + "  ");}});}
    }
  • 输出结果:单列集合
    在这里插入图片描述

  • 代码示例2:双列集合

    package text.text02;import java.util.HashMap;
    import java.util.Map;
    import java.util.Set;
    import java.util.function.Consumer;/*生成方法:
    双列集合    | 无
    双列集合无stream流,必须先利用keySet()或者entrySet()方法转化成单列集合才可以使用| 获取方式    | 方法名                                        | 说明                     |
    | ----------- | --------------------------------------------- | ------------------------ |
    | 单列集合    | default Stream<E>stream()                     | Collection中的默认方法   |
    | 双列集合    | 无                                            | 无法直接使用stream流     |
    | 数组        | public static <T> Stream<T> stream(T[] array) | Arrays工具类中的静态方法 |
    | -堆零散数据 | public static<T>Stream<T> of(T... values)     | Stream接口中的静态方法   |
    */
    public class text64 {public static void main(String[] args) {//创建双列集合HashMap<String, Integer> hm = new HashMap<>();//添加数据hm.put("手机", 1003);hm.put("电脑", 1005);hm.put("平板", 1001);hm.put("汽车", 1002);hm.put("飞机", 1004);//利用keySet()转化成单列集合System.out.println("===============利用keySet()转化成单列集合===============");method1(hm);//利用entrySet()方法转化成单列集合System.out.println("===============利用entrySet()方法转化成单列集合===============");method2(hm);}//利用entrySet()方法转化成单列集合private static void method2(HashMap<String, Integer> hm) {//将双列集合转成单列集合(entrySet()方法)Set<Map.Entry<String, Integer>> entries = hm.entrySet();entries.stream().forEach(new Consumer<Map.Entry<String, Integer>>() {@Overridepublic void accept(Map.Entry<String, Integer> stringIntegerEntry) {System.out.println(stringIntegerEntry);}});}//利用keySet()转化成单列集合private static void method1(HashMap<String, Integer> hm) {//将双列集合转成单列集合(keySet()方法)Set<String> set = hm.keySet();set.stream().forEach(new Consumer<String>() {@Overridepublic void accept(String key) {Integer value = hm.get(key);System.out.println(key + " = " + value);}});}
    }
  • 输出结果:双列集合

    • 利用keySet()转化成单列集合
      在这里插入图片描述

    • 利用entrySet()方法转化成单列集合
      在这里插入图片描述

  • 代码示例3:数组

    package text.text02;import java.util.Arrays;
    import java.util.stream.Stream;/*生成方法:数组        | public static <T> Stream<T> stream(T[] array)
    注意:Stream接口中的静态方法of的细节:方法的形参是一个可变参数,可以传递一堆零散的数据,也可以传递数组但是数组只能是引用数据类型的,如果传递基本数据类型的,是会把整个数组当成一个元素,放到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接口中的静态方法   |*/
    public class text65 {public static void main(String[] args) {//创建数组int[] arr = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};//使用Arrays里的stream方法Arrays.stream(arr).forEach(s -> System.out.println(s));//直接使用Stream里的of方法//注意:Stream接口中的静态方法of的细节//方法的形参是一个可变参数,可以传递一堆零散的数据,也可以传递数组//但是数组只能是引用数据类型的,如果传递基本数据类型的,是会把整个数组当成一个元素,放到Stream流中Stream.of(arr).forEach(s -> System.out.println(s));   //[I@3d075dc0}
    }
  • 输出结果:数组

    • 使用静态Stream方法
      在这里插入图片描述

    • 直接使用Stream里的of方法
      在这里插入图片描述

  • 代码示例4:一堆零散数据

    package text.text02;import java.util.function.Consumer;
    import java.util.stream.Stream;/*生成方法:一堆零散数据 | public static<T>Stream<T> of(T... values)
    必须是同一种数据类型| 获取方式    | 方法名                                        | 说明                     |
    | ----------- | --------------------------------------------- | ------------------------ |
    | 单列集合    | default Stream<E>stream()                     | Collection中的默认方法   |
    | 双列集合    | 无                                            | 无法直接使用stream流     |
    | 数组        | public static <T> Stream<T> stream(T[] array) | Arrays工具类中的静态方法 |
    | -堆零散数据 | public static<T>Stream<T> of(T... values)     | Stream接口中的静态方法   |
    */
    public class text66 {public static void main(String[] args) {//创建stream流并输出Stream.of("aaa", "bbb", "ccc", "ddd", "eee", "fff", "ggg", "hhh", "iii", "jjj", "kkk").forEach(new Consumer<String>() {@Overridepublic void accept(String s) {System.out.println(s);}});}
    }
    
  • 输出结果:一堆零散数据
    在这里插入图片描述

2.2 中间操作方法

2.2.1 概述

当处理 Java 8+ 中的 Stream 流时,中间操作方法用于对流中的元素进行处理和转换。

中间操作的意思是,执行完此方法之后,Stream流依然可以继续执行其他操作

2.2.2 方法
方法名说明
Stream filter(Predicate<? super T> predicate)用于对流中的数据进行过滤。只保留满足给定条件的元素。
Stream limit(long maxSize)获取流中的前N个元素,如果流中的元素数量小于N,则返回流中的所有元素。
Stream skip(long n)跳过流中的前N个元素,返回剩余的元素。如果流中的元素数量小于N,则返回空流。
Stream distinct()对流中的元素进行去重操作,去重依赖元素的hashCode和equals方法。如果是自定义对象,需要重写hashCode和equals方法。
static Stream concat(Stream a, Stream b)将两个流a和b合并为一个流,按照a流的顺序先输出,然后按照b流的顺序输出。
Stream map(Function<T,R> mapper)对流中的每个元素进行映射操作,将其转换为另一种类型的元素,通过给定的函数进行转换。
  • 注意1: 中间方法,返回新的Stream流,原来的Stream流只能使用一次,建议使用链式编程
  • 注意2: 修改Stream流中的数据,不会影响原来集合或者数组中的数据

细节:

  • filter方法获取流中的每一个数据.而test方法中的s就依次表示流中的每一个数据.我们只要在test方法中对s进行判断就可以了.
    • 如果判断的结果为true,则当前的数据留下

    • 如果判断的结果为false,则当前数据就不要.

2.2.3 代码示例
  • 代码示例
    package text.text02;import java.util.ArrayList;
    import java.util.Collections;
    import java.util.function.Consumer;
    import java.util.function.Function;
    import java.util.function.Predicate;
    import java.util.stream.Stream;/*操作方法:
    | 方法名                                         | 说明
    | ----------------------------------------------- | -----------------------------------------------------
    | Stream<T> filter(Predicate<? super T> predicate) | 用于对流中的数据进行过滤
    | Stream<T> limit(long maxSize)                    | 获取前几个元素
    | Stream<T> skip(long n)                          | 跳过前几个元素
    | Stream<T> distinct()                            | 元素去重,依赖(hashcode和equals方法)(如果是自定义对象,必须重写hashcode和equals方法)
    | static<T> Stream<T>concat(Stream a, Stream b)    | 合并a和b两个流为一个流
    | Stream<R> map(Function<T,R> mapper)              | 转换流中的数据类型- 注意1:中间方法,返回新的Stream流,原来的Stream流只能使用一次,建议使用链式编程
    - 注意2:修改Stream流中的数据,不会影响原来集合或者数组中的数据*/
    public class text67 {public static void main(String[] args) {//创建集合并添加数据ArrayList<String> list = new ArrayList<>();Collections.addAll(list, "吕布", "吕布", "吕布", "吕布", "吕布", "貂蝉", "小乔", "孙策", "大乔", "露娜", "刘备", "孙悟空", "凯", "亚瑟", "刘邦", "项羽", "张飞", "武则天", "钟无艳", "孙膑", "赵云", "妲己", "公孙离");//1.Stream<T> filter(Predicate<? super T> predicate): 用于对流中的数据进行过滤System.out.println("==========1.Stream<T> filter(Predicate<? super T> predicate): 用于对流中的数据进行过滤==========");System.out.println("以“张”开头的姓名有:");//获取Stream流对象list.stream()//调用Stream流中的filter()过滤方法.filter(new Predicate<String>() {@Override//filter方法获取流中的 每一个数据.//而test方法中的s就依次表示流中的每一个数据.//我们只要在test方法中对s进行判断就可以了.//如果判断的结果为true,则当前的数据留下//如果判断的结果为false,则当前数据就不要.public boolean test(String s) {return s.startsWith("孙");}})//遍历输出Stream流.forEach(new Consumer<String>() {@Overridepublic void accept(String s) {System.out.print(s + "  ");}});System.out.println();//2.Stream<T> limit(long maxSize) : 获取前几个元素System.out.println("==========2.Stream<T> limit(long maxSize) : 获取前几个元素==========");System.out.println("获取前5个元素是:");//获取Stream流对象list.stream()//调用Stream流中的limit()方法.limit(5)//遍历Stream流.forEach(new Consumer<String>() {@Overridepublic void accept(String s) {System.out.print(s + "  ");}});System.out.println();//3.Stream<T> skip(long n):跳过前几个元素System.out.println("==========3.Stream<T> skip(long n):跳过前几个元素==========");System.out.println("跳过前5个元素,剩下的元素是:");//获取Stream流对象list.stream()//调用Stream中的skip()方法.skip(5)//遍历Stream流.forEach(new Consumer<String>() {@Overridepublic void accept(String s) {System.out.print(s + "  ");}});System.out.println();//4.Stream<T> distinct() :元素去重,依赖(hashcode和equals方法)// (如果是自定义对象,必须重写hashcode和equals方法)System.out.println("==========4.Stream<T> distinct() :元素去重,依赖(hashcode和equals方法)==========");System.out.println("元素去重后的元素是:");//获取Stream流对象list.stream()//调用Stream流中的distinct()方法.distinct()//遍历Stream流.forEach(new Consumer<String>() {@Overridepublic void accept(String s) {System.out.print(s + "  ");}});System.out.println();//5.static<T> Stream<T> concat(Stream a, Stream b) : 合并a和b两个流为一个流//注意:如果合并的两个流是同种数据类型,则合并后的流也是该数据类型//     如果合并的两个流不是同种数据类型,则合并后的流是父类数据类型,且不能使用子类的方法System.out.println("==========5.static<T> Stream<T>concat(Stream a, Stream b) : 合并a和b两个流为一个流==========");System.out.println("将list流和list1流合并后的元素为:");//创建list1集合ArrayList<String> list1 = new ArrayList<>();Collections.addAll(list1, "张三丰", "张无忌", "张翠山", "王二麻子", "张良", "谢广坤");//调用Stream流中的concat方法(静态方法直接通过类名调用)Stream.concat(list1.stream(), list.stream())//遍历Stream流.forEach(new Consumer<String>() {@Overridepublic void accept(String s) {System.out.print(s + "  ");}});System.out.println();//6.Stream<R> map(Function<T,R> mapper): 转换流中的数据类型System.out.println("==========6.Stream<R> map(Function<T,R> mapper): 转换流中的数据类型 ==========");System.out.println("流中的年龄为:");ArrayList<String> list2 = new ArrayList<>();Collections.addAll(list2, "张三丰-11", "张无忌-12", "张翠山-12", "王二麻子-23", "张良-14", "谢广坤-15");//获取Stream流对象list2.stream()//调用Stream流中的map方法(第一个类型:流中原本的类型;第二个类型:要转成的类型).map(new Function<String, Integer>() {@Override//apply方法的参数s:依次表示流中的每一个数据//返回值:表示要转换之后的数据public Integer apply(String s) {//根据“-”分割字符串String[] arr = s.split("-");//获取字符串分割后的年龄String ageString = arr[1];//将字符串类型转换成Integer类型int age = Integer.parseInt(ageString);return age;}})//遍历Stream流.forEach(new Consumer<Integer>() {@Overridepublic void accept(Integer integer) {System.out.print(integer + "  ");}});System.out.println();System.out.println("简写方式:");//简写方式list2.stream().map(s -> Integer.parseInt(s.split("-")[1])).forEach(s -> System.out.print(s + "  "));}
    }
  • 输出结果
    • 1.Stream filter(Predicate<? super T> predicate): 用于对流中的数据进行过滤
      在这里插入图片描述

    • 2.Stream limit(long maxSize) : 获取前几个元素
      在这里插入图片描述

    • 3.Stream skip(long n):跳过前几个元素
      在这里插入图片描述

    • 4.Stream distinct() :元素去重,依赖(hashcode和equals方法)
      在这里插入图片描述

    • 5.static Streamconcat(Stream a, Stream b) : 合并a和b两个流为一个流
      在这里插入图片描述

    • 6.Stream map(Function<T,R> mapper): 转换流中的数据类型
      在这里插入图片描述

2.3 终结操作方法

2.3.1 概述

在处理 Java 8+ 中的 Stream 流时,可以通过终端操作方法来触发对流的处理,并生成最终的结果。

终结方法:终结操作的意思是,执行完此方法之后,Stream流将不能再执行其他操作

2.3.2 方法
方法名说明
void forEach(Consumer action)对此流的每个元素执行遍历操作
long count()统计
toArray()收集流中的数据,放到数组中
collect(Collector collector)收集流中的数据,放到集合中

细节:

  • toArray方法的参数的作用:负责创建一个指定类型的数组
  • toArray方法的返回值:是一个装着流里面所有数据的数组
2.3.3 代码示例
  • 代码示例
    package text.text02;import java.util.ArrayList;
    import java.util.Arrays;
    import java.util.Collections;
    import java.util.function.Consumer;
    import java.util.function.IntFunction;/*终结方法:终结操作的意思是,执行完此方法之后,Stream流将不能再执行其他操作| 方法名                        | 说明
    | ----------------------------- | ------------------------
    | void forEach(Consumer action) | 对此流的每个元素执行遍历操作
    | long count()                  | 统计
    | toArray()                     | 收集流中的数据,放到数组中
    | collect(Collector collector)  | 收集流中的数据,放到集合中
    细节:· toArray方法的参数的作用:负责创建一个指定类型的数组· toArray方法的返回值:是一个装着流里面所有数据的数组*/
    public class text68 {public static void main(String[] args) {//创建集合并添加数据ArrayList<String> list = new ArrayList<>();Collections.addAll(list, "吕布", "吕布", "吕布", "吕布", "吕布", "貂蝉", "小乔", "孙策", "大乔", "露娜", "刘备");System.out.println();//1.void forEach(Consumer action): 对此流的每个元素执行遍历操作System.out.println("==========1.void forEach(Consumer action): 对此流的每个元素执行遍历操作==========");//完整写法System.out.println("完整写法:");list.stream().forEach(new Consumer<String>() {@Overridepublic void accept(String s) {System.out.print(s + "  ");}});System.out.println();//简单写法System.out.println("简单写法:");list.stream().forEach(s -> System.out.print(s + "  "));System.out.println();//2.long count() : 统计System.out.println("==========2.long count() : 统计==========");//完整写法System.out.print("完整写法:");long count = list.stream().count();System.out.println(count);//简单写法System.out.print("简单写法:");System.out.println(list.stream().count());//3.toArray() : 收集流中的数据,放到数组中System.out.println("==========3.toArray() : 收集流中的数据,放到数组中==========");//参数为空System.out.print("参数为空:");Object[] arr1 = list.stream().toArray();System.out.println(Arrays.toString(arr1));//参数不为空System.out.println("参数不为空:");//完整形式System.out.println("完整形式:");String[] arr2 = list.stream()//IntFunction的泛型:具体类型的数组//toArray方法的参数的作用:负责创建一个指定类型的数组//toArray方法的返回值:是一个装着流里面所有数据的数组.toArray(new IntFunction<String[]>() {@Override//apply的形参:流中数组的个数,要跟数组的长度保持一致//apply的返回值:集体类型的数组public String[] apply(int value) {return new String[value];}});System.out.println(Arrays.toString(arr2));//简单形式System.out.println("简单形式:");System.out.println(Arrays.toString(list.stream().toArray(value -> new String[value])));}
    }
  • 输出结果
    • 1.void forEach(Consumer action): 对此流的每个元素执行遍历操作
      在这里插入图片描述

    • 2.long count() : 统计
      在这里插入图片描述

    • 3.toArray() : 收集流中的数据,放到数组中
      在这里插入图片描述

2.4 收集操作方法

2.4.1 概述

在 Java 8+ 中,Stream 提供了强大的收集操作方法,可以将流中的元素收集到不同类型的集合中或者生成其他形式的结果。

2.4.2 方法

collect(Collector collector) | 收集流中的数据,放到集合中 (List、Set、Map)

  • toMap:

    • 参数一表示键的生成规则
    • 参数二表示值的生成规则
  • 参数一:

    • Function
      • 泛型一:表示流中每一个数据的;

      • 泛型二:表示Map集合中键的

    • apply方法
      • 形参:依次表示流里面的每一个数
      • 方法体:生成键的代码
      • 返回值:已经生成的键
  • 参数二:

    • Function
      • 泛型一:表示流中每一个数据的

      • 泛型二:表示Map集合中值的

    • apply方法
      • 形参:依次表示流里面的每一个数

      • 方法体:生成值的代码

      • 返回值:已经生成的值

注意:如果要收集到Map集合当中,键不能重复,否则会报错

工具类Collectors提供了具体的收集方式:

方法名说明
public static Collector toList()把元素收集到List集合中
public static Collector toSet()把元素收集到Set集合中
public static Collector toMap(Function keyMapper, Function valueMapper)把元素收集到Map集合中
2.4.3 代码示例
  • 代码示例
    package text.text02;import java.util.*;
    import java.util.function.Function;
    import java.util.function.Predicate;
    import java.util.stream.Collectors;/*collect(Collector collector)  | 收集流中的数据,放到集合中 (List、Set、Map)toMap:参数一表示键的生成规则参数二表示值的生成规则
    参数一:Function泛型一:表示流中每一个数据的泛型二:表示Map集合中键的apply方法形参:依次表示流里面的每一个数方法体:生成键的代码返回值:已经生成的键
    参数二:Function泛型一:表示流中每一个数据的泛型二:表示Map集合中值的apply方法形参:依次表示流里面的每一个数方法体:生成值的代码返回值:已经生成的值注意:如果要收集到Map集合当中,键不能重复,否则会报错工具类Collectors提供了具体的收集方式| 方法名                                                       | 说明                   |
    | ------------------------------------------------------------ | ---------------------- |
    | public static <T> Collector toList()                         | 把元素收集到List集合中 |
    | public static <T> Collector toSet()                          | 把元素收集到Set集合中  |
    | public static  Collector toMap(Function keyMapper,Function valueMapper) | 把元素收集到Map集合中  |*/
    public class text69 {public static void main(String[] args) {//创建集合对象并添加元素ArrayList<String> list = new ArrayList<>();Collections.addAll(list, "吕布-男-14", "吕布-男-14", "吕布-男-14", "吕布-男-14", "吕布-男-14", "貂蝉-女-13", "小乔-女-16", "孙策-男-17", "大乔-女-17", "露娜-女-15", "刘备-男-18");//1.把元素收集到List集合中//需求:将男生收集到List集合System.out.println("===================1.把元素收集到List集合中===================");//完整模式System.out.println("完整模式:");//创建Stream对象List<String> collect1 = list.stream()//调用Stream流里的filter()过滤方法.filter(new Predicate<String>() {@Overridepublic boolean test(String s) {//分割字符串String[] arr1 = s.split("-");//获取分割之后的索引为1的字符串String s1 = arr1[1];return "男".equals(s1);}})//调用Stream流中的collect方法.collect(Collectors.toList());System.out.println(collect1);//简写模式System.out.println("简写模式:");System.out.println(list.stream().filter(s -> "男".equals(s.split("-")[1])).collect(Collectors.toList()));//2.把元素收集到Set集合中//需求:将男生收集到Set集合System.out.println("===================2.把元素收集到Set集合中===================");//完整模式System.out.println("完整模式:");//创建Stream对象Set<String> collect2 = list.stream()//调用Stream流里的filter()过滤方法.filter(new Predicate<String>() {@Overridepublic boolean test(String s) {//分割字符串String[] arr1 = s.split("-");//获取分割之后的索引为1的字符串String s1 = arr1[1];return "男".equals(s1);}})//调用Stream流中的collect方法.collect(Collectors.toSet());System.out.println(collect2);//简写模式System.out.println("简写模式:");System.out.println(list.stream().filter(s -> "男".equals(s.split("-")[1])).collect(Collectors.toSet()));//3.把元素收集到Map集合中//注意:如果要收集到Map集合当中,键不能重复,否则会报错//创建不重复的集合对象并添加元素ArrayList<String> list1 = new ArrayList<>();Collections.addAll(list1, "吕布-男-14", "貂蝉-女-13", "小乔-女-16", "孙策-男-17", "大乔-女-17", "露娜-女-15", "刘备-男-18");System.out.println("===================3.把元素收集到Map集合中===================");//完整模式System.out.println("完整模式:");Map<String, Integer> collect = list1.stream()//调用Stream里的filter过滤方法.filter(new Predicate<String>() {@Overridepublic boolean test(String s) {//分割字符串String[] split = s.split("-");//获取分割字符串之后的索引为1的字符串String s1 = split[1];return "男".equals(s1);}})/*toMap:参数一表示键的生成规则参数二表示值的生成规则参数一:Function泛型一:表示流中每一个数据的类型泛型二:表示Map集合中键的数据类型apply方法形参:依次表示流里面的每一个数据方法体:生成键的代码返回值:已经生成的键参数二:Function泛型一:表示流中每一个数据的类型泛型二:表示Map集合中值的数据类型apply方法形参:依次表示流里面的每一个数据方法体:生成值的代码返回值:已经生成的值*/.collect(Collectors.toMap(new Function<String, String>() {@Override//生成键public String apply(String key) {//获取分割字符串之后的索引为0的字符串String s = key.split("-")[0];return s;}}, new Function<String, Integer>() {@Override//生成值public Integer apply(String value) {//获取分割字符串之后的索引为2的字符串String s = value.split("-")[2];//将字符串转换成Integer类型int i = Integer.parseInt(s);return i;}}));System.out.println(collect);//简写模式System.out.println("简写模式:");System.out.println(list1.stream().filter(s -> "男".equals(s.split("-")[1])).collect(Collectors.toMap(key -> key.split("-")[0], value -> Integer.parseInt(value.split("-")[2]))));}
    }
  • 输出结果
    • 1.把元素收集到List集合中
      在这里插入图片描述

    • 2.把元素收集到Set集合中
      在这里插入图片描述

    • 3.把元素收集到Map集合中
      在这里插入图片描述

3. 代码示例1

  • 代码示例
    数据过滤: 定义一个集合,并添加一些整数1,2,3,4,5,6,7,8,9,10;过滤奇数,只留下偶数,并将结果保存起来。
    package text.text02;import java.util.ArrayList;
    import java.util.Collections;
    import java.util.List;
    import java.util.function.Predicate;
    import java.util.stream.Collectors;/*
    数据过滤:定义一个集合,并添加一些整数1,2,3,4,5,6,7,8,9,10;过滤奇数,只留下偶数,并将结果保存起来。*/
    public class text70 {public static void main(String[] args) {//定义集合并添加数据ArrayList<Integer> list = new ArrayList<>();Collections.addAll(list, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10);//完整模式System.out.println("完整模式:");List<Integer> collect = list.stream()//过滤.filter(new Predicate<Integer>() {@Overridepublic boolean test(Integer integer) {//如果判断的结果为true,则当前的数据留下//如果判断的结果为false,则当前数据就不要.return integer % 2 == 0;}})//保存数据.collect(Collectors.toList());//输出保存的集合System.out.println(collect);    //[2, 4, 6, 8, 10]//省略模式System.out.println("省略模式:");System.out.println(list.stream().filter(n -> n % 2 == 0).collect(Collectors.toList()));}
    }
  • 输出结果
    在这里插入图片描述

4. 代码示例2

  • 代码示例
    数据操作:创建一个ArrayList集合,并添加以下字符串,字符串中前面的是姓名,后面是年龄,保留年龄大于等于24岁的人,并将结果收集到Map集合中,姓名为键,年龄为值

      "zhangsan,23""lisi,24""wangwu,25"
    
    package text.text02;import java.util.ArrayList;
    import java.util.Collections;
    import java.util.Map;
    import java.util.function.Function;
    import java.util.function.Predicate;
    import java.util.stream.Collectors;/*
    数据操作:
    创建一个ArrayList集合,并添加以下字符串,字符串中前面的是姓名,后面是年龄
    "zhangsan,23"
    "lisi,24"
    "wangwu,25"
    保留年龄大于等于24岁的人,并将结果收集到Map集合中,姓名为键,年龄为值*/
    public class text71 {public static void main(String[] args) {//创建集合,并添加字符串ArrayList<String> list = new ArrayList<>();Collections.addAll(list, "zhangsan,23", "lisi,24", "wangwu,25");//完整模式System.out.println("完整模式:");Map<String, Integer> map = list.stream()//过滤.filter(new Predicate<String>() {@Overridepublic boolean test(String s) {String[] split = s.split(",");String s1 = split[1];int age = Integer.parseInt(s1);return age >= 24;}})//收集数据(保存).collect(Collectors.toMap(//键new Function<String, String>() {@Overridepublic String apply(String s) {return s.split(",")[0];}}//值, new Function<String, Integer>() {@Overridepublic Integer apply(String s) {return Integer.parseInt(s.split(",")[1]);}}));System.out.println(map);    //{lisi=24, wangwu=25}//省略模式System.out.println("省略模式:");System.out.println(list.stream().filter(s -> Integer.parseInt(s.split(",")[1]) >= 24).collect(Collectors.toMap(key -> key.split(",")[0], value -> Integer.parseInt(value.split(",")[1]))));}
    }
  • 输出结果
    在这里插入图片描述

5. 代码示例3

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

    要求完成如下操作:

    1. 男演员只要名字为3个字的前两人

    2. 女演员只要姓杨的,并且不要第一个

    3. 把过滤后的男演员姓名和女演员姓名合并到一起

    4. 将上一步的演员信息封装成Actor对象

    5. 将所有的演员对象都保存到List集合中

    备注:演员类:Actor,属性:name,age

    package text.text02;import java.util.ArrayList;
    import java.util.function.Consumer;
    import java.util.function.Function;
    import java.util.stream.Collectors;
    import java.util.stream.Stream;/*
    现在有两个ArrayList集合,第一个集合中:存储6名男演员的名字和年龄。第二个集合中,存储6名女演员的名字和年龄,姓名和年龄之间用逗号隔开。比如:张三,23
    要求完成如下操作:
    1.男演员只要名字为3个字的前两人
    2.女演员只要姓杨的,并且不要第一个
    3.把过滤后的男演员姓名和女演员姓名合并到一起
    4.将上一步的演员信息封装成Actor对象
    5.将所有的演员对象都保存到List集合中
    备注:演员类:Actor,属性:name,age*/
    public class text72 {public static void main(String[] args) {//创建集合ArrayList<String> manList = new ArrayList<String>();manList.add("周润发,23");manList.add("成龙,24");manList.add("刘德华,46");manList.add("吴京,14");manList.add("周星驰,25");manList.add("李连杰,54");ArrayList<String> womanList = new ArrayList<String>();womanList.add("林心如,24");womanList.add("张曼玉,35");womanList.add("杨幂,15");womanList.add("杨柳岩,23");womanList.add("林志玲,45");womanList.add("杨祖贤,23");//1.男演员只要名字为3个字的前两人Stream<String> manStream = manList.stream().filter(s -> s.split(",")[0].length() == 3).limit(2);//2.女演员只要姓杨的,并且不要第一个Stream<String> womenStream = womanList.stream().filter(s -> s.split(",")[0].startsWith("杨")).skip(1);//3.把过滤后的男演员姓名和女演员姓名合并到一起Stream<String> stream = Stream.concat(manStream, womenStream);//4.将上一步的演员信息封装成Actor对象stream.map(new Function<String, Actor>() {@Overridepublic Actor apply(String s) {//获取姓名String name = s.split(",")[0];//获取年龄int age = Integer.parseInt(s.split(",")[1]);//返回对象return new Actor(name, age);}})//5.将所有的演员对象都保存到List集合中.collect(Collectors.toList())//遍历保存的List集合集合.forEach(new Consumer<Actor>() {@Overridepublic void accept(Actor actor) {System.out.println(actor.getName() + " , " + actor.getAge());}});}
    }class Actor {private String name;private int age;public Actor() {}public Actor(String name, int age) {this.name = name;this.age = age;}/*** 获取** @return name*/public String getName() {return name;}/*** 设置** @param name*/public void setName(String name) {this.name = name;}/*** 获取** @return age*/public int getAge() {return age;}/*** 设置** @param age*/public void setAge(int age) {this.age = age;}public String toString() {return "Actor{name = " + name + ", age = " + age + "}";}
    }
  • 输出结果
    在这里插入图片描述

6. 注意事项

  1. 流只能遍历一次:一旦对流进行了终端操作,比如使用了终端操作方法或者转换为了一个集合,流就已经被消耗完毕,不能再进行其他操作。如果需要对流进行多次操作,可以通过创建新的流来实现。

  2. 及早终止操作:流中定义的操作分为两类:中间操作和终端操作。中间操作像过滤、映射等只返回一个新的流,而终端操作才会触发流的处理。如果不进行终端操作,中间操作不会被执行。

  3. 流的惰性求值:在执行终端操作之前,中间操作不会立即执行。只有在需要结果时,才会触发中间操作执行。这种延迟求值的特性可以提高性能。

  4. 避免使用无限流:Stream 提供了生成无限流的方法,如 iterate 和 generate。使用时要特别小心,确保有适当的终止条件,否则会导致无限循环。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/681915.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Linux入门(1)Linux介绍

目录 1. 认识 Linux, 了解 Linux 的相关背景 1.发展史 2. 学会如何使用云服务器 3. 掌握使用远程终端工具 xshell 登陆 Linux 服务器 1. 认识 Linux, 了解 Linux 的相关背景 1.发展史 学习Linux系统编程&#xff0c;你可能要问Linux从哪里来&#xff1f;它是怎么发展的&am…

百面嵌入式专栏(面试题)驱动开发面试题汇总 2.0

沉淀、分享、成长,让自己和他人都能有所收获!😄 📢本篇我们将介绍驱动开发面试题 。 1、Linux系统的组成部分? Linux内核、Linux文件系统、Linux shell、Linux应用程序。 2、Linux内核的组成部分? (1)第一种分类方式:内存管理子系统、进程管理子系统、文件管理子系…

RSIC-V“一芯”学习笔记(三)——读后感以及部分PA0工作

文章目录 一、别像弱智一样提问二、提问的智慧三、安装linux以及配置问题3.1 关于问题配置 一、别像弱智一样提问 提问前&#xff0c;应该清晰问自己几个问题&#xff0c;1. 是否尝试了在搜索引擎进行搜索过2. 相关的手册和文档是否看了3. 找找有没有常见的问题文档&#xff0…

Vue--》深入学习Tailwind CSS掌握优雅而高效的前端样式开发

Tailwind CSS是一个非常强大且灵活的CSS框架&#xff0c;适用于开发者希望高度定制化界面样式的项目。今天博主就 Tailwind CSS 做一个简单介绍以及案例讲解&#xff0c;争取读者阅读文章后入门。 仅靠一篇文章博主也不可能将Tailwind CSS所有内容讲解的面面俱到&#xff0c;在…

66万个 全国行政区划代码表

66万个全国各级行政区划代码表 提供的数据一览 简介 一共有66万个全国各级行政区划&#xff0c;一共有5个级别的行政单位级别 表格头部数据 表格尾部数据 全国行政单位各省份数量统计 数据下载地址 数据整理不易 百度云盘 链接: https://pan.baidu.com/s/1o1C2piYj2wu…

软件实例分享,宠物店兽医电子处方开单系统软件教程

软件实例分享&#xff0c;宠物店兽医电子处方开单系统软件教程 一、软件教程问答 以下教程以 佳易王宠物店兽医电子处方软件V16.0为例说明 软件文件下载可以点击最下方官网卡片——软件下载——试用版软件下载 问&#xff1a;宠物医院电子处方单子使用的纸张大小是多少&…

树莓派编程基础与硬件控制

1.编程语言 Python 是一种泛用型的编程语言&#xff0c;可以用于大量场景的程序开发中。根据基于谷歌搜 索指数的 PYPL&#xff08;程序语言流行指数&#xff09;统计&#xff0c;Python 是 2019 年 2 月全球范围内最为流行 的编程语言 相比传统的 C、Java 等编程语言&#x…

compile error ESP32cam.h no such file or directory

解决方法 可以参考这篇文章&#xff1a; But first, you will need to download the esp32cam.h library. For this go to Github and download the esp32cam Zip. GitHub - yoursunny/esp32cam: OV2640 camera on ESP32-CAM, Arduino library 具体就是下面的这篇重要的文章 …

URL编码算法:解决特殊字符在URL中的烦恼

引言&#xff1a; URL编码算法是一种将URL中的特殊字符转换为特定格式的编码方式。它在网络传输中起到了保护数据安全与完整性的重要作用。本文将深入探讨URL编码算法的优点与缺点&#xff0c;并介绍它在Web开发、网络安全等方面的应用。 URL编码解码 | 一个覆盖广泛主题工具…

抽象工厂模式-Abstract Factory Pattern

原文地址:https://jaune162.blog/design-pattern/abstract-factory-pattern/ 引言 首先我们由一个实际问题来引出抽象工厂模式。 考虑这样一个场景,系统中需要向OSS上传文件,以及通过OSS下载文件。而在系统中有不同的业务在使用这两个功能。如下图: 伪代码如下 public in…

怎么使用ChatGPT提高工作效率?

怎么使用ChatGPT提高工作效率&#xff0c;这是一个有趣的话题。 相信不同的人有不同的观点&#xff0c;大家的知识背景和从事的工作都不完全相同&#xff0c;所以最终ChatGPT能起到的作用也不一样。 在编程过程中&#xff0c;如果我们要找一个库&#xff0c;我们最先做的肯定…

算法讲解之字符串

前言&#xff1a; 本文主要讲解算法中和字符串结合的题目&#xff0c;跟字符串结合的算法题种类丰富&#xff0c;主要是跟别的算法结合&#xff0c;下面介绍几道比较经典的题目~ 第一道&#xff1a;14. 最长公共前缀 题目描述&#xff1a; 编写一个函数来查找字符串数组中的…

987. 二叉树的垂序遍历 - 力扣(LeetCode)

题目描述 给你二叉树的根结点 root &#xff0c;请你设计算法计算二叉树的 垂序遍历 序列。 对位于 (row, col) 的每个结点而言&#xff0c;其左右子结点分别位于 (row 1, col - 1) 和 (row 1, col 1) 。树的根结点位于 (0, 0) 。 二叉树的 垂序遍历 从最左边的列开始直到…

生活篇——华为手机去除负一屏

华为手机去除如下图的恶心负一屏 打开华为的应用市场app 进入&#xff1a;我的-设置-国家/地区&#xff08;改为俄罗斯&#xff09;-进入智慧助手检查更新并更新智慧助手。 然后重复开始的操作&#xff0c;将地区改回中国&#xff0c;这样就没有负一屏了。

初中生用什么台灯最好?精选高口碑的学生护眼台灯

其实现在的孩子从上初中开始&#xff0c;他们的学习压力就已经很大了&#xff0c;繁重的功课让他们经常用眼过度&#xff0c;导致早早就戴上小眼镜。所以要想孩子拥有一个良好的视力健康&#xff0c;不仅要从日常的坐姿、用眼习惯开始纠正、培养&#xff0c;夜晚学习时的那一盏…

状态监测防火墙详细工作流程

状态监测防火墙是一种用于监测和分析网络通信状态的安全设备。其工作流程通常包括以下几个步骤&#xff1a; 1. 采集数据&#xff1a;防火墙会采集来自网络流量的数据&#xff0c;包括 IP 地址、端口号、协议类型等信息&#xff0c;并将其存储在数据库中。 2. 分析数据&#xf…

CPython:表达式的求值顺序(evaluation order)

相关阅读 Pythonhttps://blog.csdn.net/weixin_45791458/category_12403403.html?spm1001.2014.3001.5482 C中表达式的求值 C语言针对表达式的计算&#xff0c;设置了操作符的优先级和结合性这两个特性&#xff0c;优先级用于解析不同优先级的符号&#xff0c;结合性用于解析…

2024年,要特别注意这两个方位

家居风水对每个家庭都非常重要&#xff0c;可在无形中影响到人们的事业、财富以及健康运势。俗话说&#xff1a;“风水轮流转”&#xff0c;2024年为甲辰龙年&#xff0c;斗转星移、九宫飞星将改变宫位&#xff0c;新一年的磁场即将启动&#xff0c;方位的吉凶也会重新变动&…

oracle单机打DBBP补丁

书接上回 ORA-600 adg无法查询故障-CSDN博客 https://blog.csdn.net/q195136130/article/details/135445378?spm1001.2014.3001.5502 单机安装DBBP 解压缩补丁包 unzip p34204559_121020_Linux-x86-64.zip 关闭数据库 su - oraclesqlplus / as sysdbashut immediate 检查…