当前位置: 首页 > 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 …...

51c自动驾驶~合集58

我自己的原文哦~ https://blog.51cto.com/whaosoft/13967107 #CCA-Attention 全局池化局部保留&#xff0c;CCA-Attention为LLM长文本建模带来突破性进展 琶洲实验室、华南理工大学联合推出关键上下文感知注意力机制&#xff08;CCA-Attention&#xff09;&#xff0c;…...

基于距离变化能量开销动态调整的WSN低功耗拓扑控制开销算法matlab仿真

目录 1.程序功能描述 2.测试软件版本以及运行结果展示 3.核心程序 4.算法仿真参数 5.算法理论概述 6.参考文献 7.完整程序 1.程序功能描述 通过动态调整节点通信的能量开销&#xff0c;平衡网络负载&#xff0c;延长WSN生命周期。具体通过建立基于距离的能量消耗模型&am…...

如何在看板中体现优先级变化

在看板中有效体现优先级变化的关键措施包括&#xff1a;采用颜色或标签标识优先级、设置任务排序规则、使用独立的优先级列或泳道、结合自动化规则同步优先级变化、建立定期的优先级审查流程。其中&#xff0c;设置任务排序规则尤其重要&#xff0c;因为它让看板视觉上直观地体…...

EtherNet/IP转DeviceNet协议网关详解

一&#xff0c;设备主要功能 疆鸿智能JH-DVN-EIP本产品是自主研发的一款EtherNet/IP从站功能的通讯网关。该产品主要功能是连接DeviceNet总线和EtherNet/IP网络&#xff0c;本网关连接到EtherNet/IP总线中做为从站使用&#xff0c;连接到DeviceNet总线中做为从站使用。 在自动…...

.Net Framework 4/C# 关键字(非常用,持续更新...)

一、is 关键字 is 关键字用于检查对象是否于给定类型兼容,如果兼容将返回 true,如果不兼容则返回 false,在进行类型转换前,可以先使用 is 关键字判断对象是否与指定类型兼容,如果兼容才进行转换,这样的转换是安全的。 例如有:首先创建一个字符串对象,然后将字符串对象隐…...

Mobile ALOHA全身模仿学习

一、题目 Mobile ALOHA&#xff1a;通过低成本全身远程操作学习双手移动操作 传统模仿学习&#xff08;Imitation Learning&#xff09;缺点&#xff1a;聚焦与桌面操作&#xff0c;缺乏通用任务所需的移动性和灵活性 本论文优点&#xff1a;&#xff08;1&#xff09;在ALOHA…...

Windows安装Miniconda

一、下载 https://www.anaconda.com/download/success 二、安装 三、配置镜像源 Anaconda/Miniconda pip 配置清华镜像源_anaconda配置清华源-CSDN博客 四、常用操作命令 Anaconda/Miniconda 基本操作命令_miniconda创建环境命令-CSDN博客...

Python 实现 Web 静态服务器(HTTP 协议)

目录 一、在本地启动 HTTP 服务器1. Windows 下安装 node.js1&#xff09;下载安装包2&#xff09;配置环境变量3&#xff09;安装镜像4&#xff09;node.js 的常用命令 2. 安装 http-server 服务3. 使用 http-server 开启服务1&#xff09;使用 http-server2&#xff09;详解 …...

Ubuntu系统复制(U盘-电脑硬盘)

所需环境 电脑自带硬盘&#xff1a;1块 (1T) U盘1&#xff1a;Ubuntu系统引导盘&#xff08;用于“U盘2”复制到“电脑自带硬盘”&#xff09; U盘2&#xff1a;Ubuntu系统盘&#xff08;1T&#xff0c;用于被复制&#xff09; &#xff01;&#xff01;&#xff01;建议“电脑…...

数据库——redis

一、Redis 介绍 1. 概述 Redis&#xff08;Remote Dictionary Server&#xff09;是一个开源的、高性能的内存键值数据库系统&#xff0c;具有以下核心特点&#xff1a; 内存存储架构&#xff1a;数据主要存储在内存中&#xff0c;提供微秒级的读写响应 多数据结构支持&…...