当前位置: 首页 > news >正文

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。使用时要特别小心,确保有适当的终止条件,否则会导致无限循环。

相关文章:

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. 代码示例14. 代码示例25. 代…...

大数据应用对企业的价值

目录 一、大数据应用价值 1.1 大数据技术分析 1.2 原有技术场景的优化 1.2.1 数据分析优化 1.2.2 高并发数据处理 1.3 通过大数据构建新需求 1.3.1 智能推荐 1.3.2 广告系统 1.3.3 产品/流程优化 1.3.4 异常检测 1.3.5 智能管理 1.3.6 人工智能和机器学习 二、大数…...

【51单片机】LED点阵屏(江科大)

9.1LED点阵屏 1.LED点阵屏介绍 LED点阵屏由若干个独立的LED组成,LED以矩阵的形式排列,以灯珠亮灭来显示文字、图片、视频等。 2.LED点阵屏工作原理 LED点阵屏的结构类似于数码管,只不过是数码管把每一列的像素以“8”字型排列而已。原理图如下 每一行的阳极连在一起,每一列…...

Microsoft OneNote 图片文字提取

Microsoft OneNote 图片文字提取 1. 文件 -> 新建 -> 我的电脑 -> 名称 -> 位置 -> 创建笔记本2. 插入图片​​​3. 复制图片中的文本References 1. 文件 -> 新建 -> 我的电脑 -> 名称 -> 位置 -> 创建笔记本 ​ 2. 插入图片 ​​​3. 复制图片…...

Linux系统安全——iptables相关总结

在使用iptables时注意要先关闭firewalld&#xff08;systemctl stop firewalld.service&#xff09; 1.查看iptables规则 iptables -vnL 选项含义-v查看时显示更多详细信息-n所有字段以数字形式显示-L查看规则列表 例&#xff0c;拒绝来自192.168.241.22的源地址 直接丢弃 …...

深度学习(14)--x.view()详解

在torch中&#xff0c;常用view()函数来改变tensor的形状 查询官方文档&#xff1a; torch.Tensor.view — PyTorch 2.2 documentationhttps://pytorch.org/docs/stable/generated/torch.Tensor.view.html#torch.Tensor.view示例 1.创建一个4x4的二维数组进行测试 x torch.…...

最新wordpress外贸主题

日用百货wordpress外贸主题 蓝色大气的wordpress外贸主题&#xff0c;适合做日用百货的外贸公司搭建跨境电商网站使用。 https://www.jianzhanpress.com/?p5248 添加剂wordpress外贸建站主题 橙色wordpress外贸建站主题&#xff0c;适合做食品添加剂或化工添加剂的外贸公司…...

Spring Cloud Gateway:使用RestController动态更新路由

相关类介绍 动态路由&#xff08;自己控制&#xff0c;非注册中心控制&#xff09;涉及两个很重要的Bean&#xff1a; RouteDefinitionWriter&#xff1a;用于添加、修改、删除路由规则。RouteDefinitionLocator&#xff1a;用于查询路由规则。 以及一个相关事件&#xff1a…...

用Python动态展示排序算法

文章目录 选择冒泡插入排序归并排序希尔排序 经常看到这种算法可视化的图片&#xff0c;但往往做不到和画图的人心灵相通&#xff0c;所以想自己画一下&#xff0c;本文主要实现归并排序和希尔排序&#xff0c;如果想实现其他算法可参考这篇 C语言实现各种排序算法[选择&#x…...

vscode代码快捷键

1、 log console.log()2、edf export default (first)>{ second } 或者 export default function(params)>{ }可以使用tab键切换修改项 3、ednf export default function first(second) {third}4、! 生成html模板 5、div#app <div id"app"></di…...

深入了解C++:形参、内联、重载、引用、const和指针、new和delete

形参带默认值的函数 1.给默认值的时候从右向左给。 2.定义出可以给形参默认值&#xff0c;声明也可以给形参默认值。 3.形参默认值只能出现一次。 4.参数调用的效率问题 #sum(10,20)对应了五条汇编指令 mov eax,dword ptr[ebp-8] push eax mov ecx dword ptr[ebp-4] push …...

Linux 目录结构结构

Linux 目录结构结构 概念 Linux 没有 C、D、E...盘符&#xff0c;只有一个目录树。通过挂载&#xff0c;将不同的磁盘挂载到目录树下&#xff0c;通过目录访问磁盘。 ‍ 不同目录的作用 目录存放内容/作用​/​根目录&#xff0c;目录树的起点&#xff0c;存放所有文件。​…...

C++基础入门:掌握核心概念(超全!)

C作为一门广泛使用的编程语言&#xff0c;以其高性能和灵活性在软件开发领域占据重要地位。无论是游戏开发、系统编程还是实时应用&#xff0c;C都是一个不可或缺的工具。本博客旨在为初学者提供C编程语言的核心概念&#xff0c;帮助你建立坚实的基础。 C关键字 C关键字是编程…...

Linux第47步_安装支持linux的第三方库和mkimage工具

安装支持linux的第三方库和mkimage工具&#xff0c;做好移植前的准备工作。 编译linux内核之前&#xff0c;需要先在 ubuntu上安装“lzop库”和“libssl-dev库”&#xff0c;否则内核编译会失败。 mkimage工具会在zImage镜像文件的前面添加0x40个字节的头部信息,就可以得到uI…...

数据工程工程师学习路线图

数据工程岗位要求 Skill Sets required: - Hands on experience enabling data via Adobe Analytics and/or Google Analytics - Understanding of how customer level data is captured and stitched with behavioural data - Experience working with Testing (QA) and D…...

MySQL主从同步与分库分表

分库分表...

百度PaddleOCR字符识别推理部署(C++)

1 环境 1.opencv&#xff08;https://sourceforge.net/projects/opencvlibrary/&#xff09; 2.cmake&#xff08;https://cmake.org/download/&#xff09; 3.vs2019&#xff08;(https://github.com/PaddlePaddle/PaddleOCR/tree/release/2.1) 4.paddleOCR项目-建议2.0(http…...

C++ Qt框架开发 | 基于Qt框架开发实时成绩显示排序系统(2)折线图显示

对上一篇的工作C学习笔记 | 基于Qt框架开发实时成绩显示排序系统1-CSDN博客继续优化&#xff0c;增加一个显示运动员每组成绩的折线图。 1&#xff09;在Qt Creator的项目文件&#xff08;.pro文件&#xff09;中添加对Qt Charts模块的支持&#xff1a; QT charts 2&#xf…...

Microsoft Excel 加载数据分析工具

Microsoft Excel 加载数据分析工具 1. 打开 Excel&#xff0c;文件 -> 选项2. 加载项 -> 转到…3. 分析工具库、分析工具库 - VBA4. 打开 Excel&#xff0c;数据 -> 数据分析References 1. 打开 Excel&#xff0c;文件 -> 选项 2. 加载项 -> 转到… ​​​ 3…...

Day32 贪心算法part02

买卖股票的最佳时机 太牛了我&#xff0c;随随便便双指针秒杀 md题解里面双指针都没用直接for循环秒杀 跳跃游戏 写成这样纯粹是没有看到第一次跳跃必须从第一个开始 class Solution:def canJump(self, nums: List[int]) -> bool:if len(nums) 1:return Truefor i in …...

XML Group端口详解

在XML数据映射过程中&#xff0c;经常需要对数据进行分组聚合操作。例如&#xff0c;当处理包含多个物料明细的XML文件时&#xff0c;可能需要将相同物料号的明细归为一组&#xff0c;或对相同物料号的数量进行求和计算。传统实现方式通常需要编写脚本代码&#xff0c;增加了开…...

零门槛NAS搭建:WinNAS如何让普通电脑秒变私有云?

一、核心优势&#xff1a;专为Windows用户设计的极简NAS WinNAS由深圳耘想存储科技开发&#xff0c;是一款收费低廉但功能全面的Windows NAS工具&#xff0c;主打“无学习成本部署” 。与其他NAS软件相比&#xff0c;其优势在于&#xff1a; 无需硬件改造&#xff1a;将任意W…...

基于当前项目通过npm包形式暴露公共组件

1.package.sjon文件配置 其中xh-flowable就是暴露出去的npm包名 2.创建tpyes文件夹&#xff0c;并新增内容 3.创建package文件夹...

css3笔记 (1) 自用

outline: none 用于移除元素获得焦点时默认的轮廓线 broder:0 用于移除边框 font-size&#xff1a;0 用于设置字体不显示 list-style: none 消除<li> 标签默认样式 margin: xx auto 版心居中 width:100% 通栏 vertical-align 作用于行内元素 / 表格单元格&#xff…...

Yolov8 目标检测蒸馏学习记录

yolov8系列模型蒸馏基本流程&#xff0c;代码下载&#xff1a;这里本人提交了一个demo:djdll/Yolov8_Distillation: Yolov8轻量化_蒸馏代码实现 在轻量化模型设计中&#xff0c;**知识蒸馏&#xff08;Knowledge Distillation&#xff09;**被广泛应用&#xff0c;作为提升模型…...

LINUX 69 FTP 客服管理系统 man 5 /etc/vsftpd/vsftpd.conf

FTP 客服管理系统 实现kefu123登录&#xff0c;不允许匿名访问&#xff0c;kefu只能访问/data/kefu目录&#xff0c;不能查看其他目录 创建账号密码 useradd kefu echo 123|passwd -stdin kefu [rootcode caozx26420]# echo 123|passwd --stdin kefu 更改用户 kefu 的密码…...

A2A JS SDK 完整教程:快速入门指南

目录 什么是 A2A JS SDK?A2A JS 安装与设置A2A JS 核心概念创建你的第一个 A2A JS 代理A2A JS 服务端开发A2A JS 客户端使用A2A JS 高级特性A2A JS 最佳实践A2A JS 故障排除 什么是 A2A JS SDK? A2A JS SDK 是一个专为 JavaScript/TypeScript 开发者设计的强大库&#xff…...

【C++特殊工具与技术】优化内存分配(一):C++中的内存分配

目录 一、C 内存的基本概念​ 1.1 内存的物理与逻辑结构​ 1.2 C 程序的内存区域划分​ 二、栈内存分配​ 2.1 栈内存的特点​ 2.2 栈内存分配示例​ 三、堆内存分配​ 3.1 new和delete操作符​ 4.2 内存泄漏与悬空指针问题​ 4.3 new和delete的重载​ 四、智能指针…...

腾讯云V3签名

想要接入腾讯云的Api&#xff0c;必然先按其文档计算出所要求的签名。 之前也调用过腾讯云的接口&#xff0c;但总是卡在签名这一步&#xff0c;最后放弃选择SDK&#xff0c;这次终于自己代码实现。 可能腾讯云翻新了接口文档&#xff0c;现在阅读起来&#xff0c;清晰了很多&…...

FFmpeg:Windows系统小白安装及其使用

一、安装 1.访问官网 Download FFmpeg 2.点击版本目录 3.选择版本点击安装 注意这里选择的是【release buids】&#xff0c;注意左上角标题 例如我安装在目录 F:\FFmpeg 4.解压 5.添加环境变量 把你解压后的bin目录&#xff08;即exe所在文件夹&#xff09;加入系统变量…...