首页
学习
活动
专区
圈层
工具
发布
社区首页 >专栏 >【愚公系列】Java教学课程 051-可变参数、不可变集合、Stream流

【愚公系列】Java教学课程 051-可变参数、不可变集合、Stream流

作者头像
愚公搬代码
发布2025-06-02 13:40:59
发布2025-06-02 13:40:59
2160
举报
文章被收录于专栏:历史专栏历史专栏

🏆 作者简介,愚公搬代码 🏆《头衔》:华为云特约编辑,华为云云享专家,华为开发者专家,华为产品云测专家,CSDN博客专家,阿里云专家博主,腾讯云优秀博主,掘金优秀博主,51CTO博客专家等。 🏆《近期荣誉》:2022年CSDN博客之星TOP2,2022年华为云十佳博主等。 🏆《博客内容》:.NET、Java、Python、Go、Node、前端、IOS、Android、鸿蒙、Linux、物联网、网络安全、大数据、人工智能、U3D游戏、小程序等相关领域知识。 🏆🎉欢迎 👍点赞✍评论⭐收藏

🚀一、可变参数

🔎1.概念

Java中可变参数是一种特殊的参数类型,允许方法在调用时使用不同数量的参数。使用可变参数可以使方法更加灵活,可以接受任意数量的参数。

可变参数由三个点(…)表示,它必须是方法的最后一个参数。在方法体内,可以将可变参数看作是数组形式的参数,因此可以使用数组的相关方法和语法来处理可变参数。

例如,下面是一个使用可变参数的方法的示例:

代码语言:javascript
复制
public static int sum(int... nums) {
    int result = 0;
    for (int n : nums) {
        result += n;
    }
    return result;
}

在调用该方法时,可以传入任意数量的参数:

代码语言:javascript
复制
int result1 = sum(1, 2, 3); // result1 = 6
int result2 = sum(1, 2, 3, 4, 5); // result2 = 15
int result3 = sum(); // result3 = 0

注意,在实际应用中,可变参数应该谨慎使用,以避免出现意外的行为。同时,使用可变参数也会对性能产生一定影响。

🔎2.作用

Java中的可变参数可以方便地将不定数量的参数传递给一个方法。这样,不需要在方法定义时确定参数的数量,从而提高了方法的灵活性和可重用性。可变参数的语法是在参数类型后面加上三个点(…),表示可以接受任意数量的参数。在方法内部,可变参数被当作一个数组来处理,可以通过循环遍历来处理每一个参数。同时,Java也提供了一些内置方法来操作可变参数,例如Arrays.asList()方法可以将一个序列转换成一个List对象。

🔎3.案例

下面是一个使用可变参数的例子,实现了一个方法来打印多个字符串:

代码语言:javascript
复制
public class VarargsExample {
    public static void main(String[] args) {
        printStrings("Hello", "World"); // 输出 "Hello World"
        printStrings("Java", "is", "fun"); // 输出 "Java is fun"
    }

    public static void printStrings(String... strings) {
        for (String s : strings) {
            System.out.print(s + " ");
        }
        System.out.println();
    }
}

在上面的代码中,我们定义了一个名为printStrings的方法,参数列表中使用了可变参数String... strings,表示可以接收任意数量的字符串参数。

在方法体内部,我们使用了一个for循环来遍历这个可变参数strings,并将每个字符串都输出到控制台上。最后,在每个字符串后面加上一个空格,最后输出一个换行符,以便下一个输出语句不会与前一个输出语句在同一行上。

🔎4.注意事项

  1. 可变参数必须是方法的最后一个参数。
  2. 可变参数只能有一个,不能出现多个。
  3. 可变参数的类型必须是数组类型,且元素类型必须确定。
  4. 可变参数可以不传递参数,此时会创建一个长度为0的数组。
  5. 如果同时有多个参数,可变参数的前面的参数类型和数量必须确定,后面的可变参数必须放在最后。
  6. 传递参数时可以使用数组,也可以使用逗号分隔的参数列表格式。
  7. 可变参数的类型不能是基本类型,只能是引用类型。

🚀二、不可变集合

🔎1.概念

Java中的不可变集合是指创建后不能被修改的集合。一旦创建了不可变集合,不能添加、删除或修改其中的元素,只能读取其中的元素。Java提供了许多不可变集合类,例如:

  1. 不可变列表:java.util.Collections.unmodifiableList()
  2. 不可变集合:java.util.Collections.unmodifiableSet()
  3. 不可变映射:java.util.Collections.unmodifiableMap()

使用不可变集合的好处是:

  1. 线程安全:不可变集合在多线程环境下是安全的,因为它们没有被修改的风险。
  2. 性能优化:由于不可变集合是不可修改的,它们可以被缓存、重复使用,从而提高性能。
  3. 代码安全性:由于不可变集合不能被修改,它们可以减少由于意外修改导致的代码错误。

值得注意的是,虽然不可变集合不能被修改,但是它们可以被替换为新的集合。例如,可以使用新的集合替换已经存在的不可变集合。这种方式可以让代码更加灵活,同时保持不可变集合的优点。

🔎2.作用

不可变集合在Java中的作用是保证数据的不可修改性,从而提高代码的安全性和可维护性。使用不可变集合可以避免在多线程环境中出现的并发问题。

Java中提供了多种不可变集合类,如不可变列表类ImmutableList、不可变集合类ImmutableSet、不可变映射类ImmutableMap等,这些类都是通过复制原始集合并在内部进行不可修改操作来实现的。

使用不可变集合的好处是:

  1. 安全性:不可变集合可以防止数据被其他代码修改,从而避免数据泄漏和安全漏洞。
  2. 可维护性:不可变集合可以减少代码维护难度,更容易理解和调试。
  3. 性能:尽管使用不可变集合类需要创建新的对象,但是由于不需要进行修改操作,因此可以获得更好的性能。此外,由于不可变集合不需要进行线程同步操作,因此在多线程环境中可以获得更好的性能。

对于需要保证安全性和可维护性的Java应用程序,使用不可变集合是一个很好的选择。

🔎3.案例

Java中提供了不可变集合类,可以使用它们创建不可变集合对象。不可变集合是指一旦创建就不能被修改的集合,任何尝试修改不可变集合的操作都将返回一个新的不可变集合对象。以下是Java中不可变集合的示例:

  1. 不可变List:
代码语言:javascript
复制
import java.util.Collections;
import java.util.List;

public class ImmutableCollectionsExample {

    public static void main(String[] args) {
        List<String> immutableList = Collections.unmodifiableList(Arrays.asList("apple", "banana", "orange"));
        System.out.println(immutableList);
        // immutableList.add("grape"); // This will throw an UnsupportedOperationException
    }
}

在上述代码中,我们使用Collections.unmodifiableList()方法创建了一个不可变List,如果尝试修改该List,将抛出UnsupportedOperationException异常。

  1. 不可变Set:
代码语言:javascript
复制
import java.util.Collections;
import java.util.HashSet;
import java.util.Set;

public class ImmutableCollectionsExample {

    public static void main(String[] args) {
        Set<String> immutableSet = Collections.unmodifiableSet(new HashSet<>(Arrays.asList("red", "green", "blue")));
        System.out.println(immutableSet);
        // immutableSet.add("yellow"); // This will throw an UnsupportedOperationException
    }
}

在上述代码中,我们使用Collections.unmodifiableSet()方法创建了一个不可变Set,如果尝试修改该Set,将抛出UnsupportedOperationException异常。

  1. 不可变Map:
代码语言:javascript
复制
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;

public class ImmutableCollectionsExample {

    public static void main(String[] args) {
        Map<String, Integer> immutableMap = Collections.unmodifiableMap(new HashMap<String, Integer>() {{
            put("apple", 1);
            put("banana", 2);
            put("orange", 3);
        }});
        System.out.println(immutableMap);
        // immutableMap.put("grape", 4); // This will throw an UnsupportedOperationException
    }
}

在上述代码中,我们使用Collections.unmodifiableMap()方法创建了一个不可变Map,如果尝试修改该Map,将抛出UnsupportedOperationException异常。

通过使用不可变集合,我们可以确保集合内容的安全性,并避免不小心改变其内容的错误。

🔎4.注意事项

Java中不可变集合是指一旦创建就不能修改的集合。它们是线程安全的,因为多个线程可以同时访问它们而不会导致数据损坏或不一致。以下是使用不可变集合时应注意的事项:

  1. 不可变集合的创建是一个开销较大的操作,因为每次修改集合时都需要创建一个新的集合对象。因此,应尽量避免在性能敏感的代码中频繁地创建不可变集合。
  2. 不可变集合不支持修改操作,因此在需要修改集合的情况下,需要使用可变集合来完成。但是,可以通过创建新的不可变集合来模拟修改操作。例如,通过使用不可变集合的“add”方法创建一个新集合来模拟添加元素的操作。
  3. 在使用不可变集合时,应注意避免在迭代或循环操作中修改集合。这可能会导致ConcurrentModificationException异常。
  4. 当使用不可变集合时,需要将其视为只读集合。尝试修改不可变集合将导致UnsupportedOperationException异常。
  5. 不可变集合可以通过Collections.unmodifiableXXX方法创建。这些方法将返回一个只读的不可变集合,而不是一个真正的不可变集合。因此,如果持有一个只读的不可变集合,应将其视为只读集合,并避免在其上执行修改操作。
  6. 不要将可变集合转换为不可变集合,因为这不是线程安全的。如果需要创建不可变集合,请使用正确的方法来创建它们。

List、Set、Map接口中,都存在of方法可以创建不可变集合,相关案例如下:

代码语言:javascript
复制
public static void main(String[] args) {
    // 1、不可变的List集合
    List<Double> lists = List.of(569.5, 700.5, 523.0,  570.5);
    // lists.add(99.9);
    System.out.println(lists.get(2));

    // 2、不可变的Set集合
    Set<String> names = Set.of("迪丽热巴", "迪丽热九", "马尔扎哈", "卡尔眨巴" );
    // names.add("迪丽热九");
    System.out.println(names);

    // 3、不可变的Map集合
    Map<String, Integer> maps = Map.of("huawei",2, "Java开发", 1 , "手表", 1);
    maps.put("huawei",100);
    System.out.println(maps);
}

🚀三、Stream流

🔎1.Stream流的概述

Java中的Stream流是一个用于处理集合数据的API,它提供了一种更加简单和直接的方式来操作集合数据。Stream流在Java 8中首次引入,它可以处理一些常见的集合操作,例如筛选、映射、聚合等。

Stream流可以分为两种类型:中间操作和终端操作。中间操作只是对数据进行转换和过滤,例如map()、filter()、distinct()等。而终端操作则是对流的数据进行计算、汇总或输出,例如count()、reduce()、forEach()等。

使用Stream流可以简化代码,提高效率和可读性,下面是Stream流的基本使用:

  1. 创建Stream流:可以通过集合、数组、IO等方式来创建Stream流;
  2. 中间操作:使用中间操作对数据进行过滤、转换等操作;
  3. 终端操作:使用终端操作对数据进行计算、汇总或输出。

例如,对于一个List集合,如果想要筛选出其中所有年龄大于18的人的名字,可以使用以下代码:

代码语言:javascript
复制
List<Person> list = new ArrayList<>();
//添加数据

List<String> names = list.stream()
                         .filter(p -> p.getAge() > 18)
                         .map(Person::getName)
                         .collect(Collectors.toList());

上述代码中,首先将List集合转换为Stream流,然后使用filter()方法筛选出年龄大于18的人,接着使用map()方法将符合条件的人的名字提取出来,最后使用collect()方法将名字转换为一个List集合。

🔎2.Stream流的获取

在Java中,Stream流可以通过以下方式获取:

  1. 从集合获取流:可以通过集合的stream()方法,将集合转换为流。例如:
代码语言:javascript
复制
List<String> list = Arrays.asList("apple", "banana", "orange");
Stream<String> stream = list.stream();
  1. 从数组获取流:可以通过Arrays类的stream()方法,将数组转换为流。例如:
代码语言:javascript
复制
int[] arr = new int[]{1, 2, 3, 4, 5};
IntStream stream = Arrays.stream(arr);
  1. 通过Stream.of()方法获取流:可以通过Stream类的of()方法,直接获取一个流。例如:
代码语言:javascript
复制
Stream<String> stream = Stream.of("apple", "banana", "orange");
  1. 通过文件获取流:可以通过Java NIO中的Files.lines()方法,从文件中获取流。例如:
代码语言:javascript
复制
Path path = Paths.get("file.txt");
Stream<String> stream = Files.lines(path);
  1. 通过生成器获取流:可以通过Stream.generate()方法,通过自定义函数生成一个流。例如:
代码语言:javascript
复制
Stream<Integer> stream = Stream.generate(() -> 1);
  1. 通过迭代器获取流:可以通过Stream.iterate()方法,通过迭代器生成一个流。例如:
代码语言:javascript
复制
Stream<Integer> stream = Stream.iterate(1, n -> n + 1);

案例如下:

代码语言:javascript
复制
public static void main(String[] args) {
    /** --------------------获取Collection系列集合的Stream流-------------------------------   */
    Collection<String> list = new ArrayList<>();
    Stream<String> s1 = list.stream();

    /** --------------------获取Map系列集合的Stream流-------------------------------   */
    Map<String, Integer> maps = new HashMap<>();
    // 键流
    Stream<String> s2 = maps.keySet().stream();
    // 值流
    Stream<Integer> s3 = maps.values().stream();
    // 键值对流(拿整体)
    Stream<Map.Entry<String, Integer>> stream = maps.entrySet().stream();

    /** ---------------------获取数组的Stream流------------------------------   */
    String[] names = {"赵敏","小昭","灭绝","周芷若"};
    // 两种写法的效果是一样的!
    Stream<String> s4 = Arrays.stream(names);
    Stream<String> s5 = Stream.of(names);
}

🔎3.Stream流的常用API

API名称

作用

示例

filter()

过滤流中的元素

List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5);List<Integer> evenNumbers = numbers.stream().filter(x -> x % 2 == 0).collect(Collectors.toList());

map()

对流中的元素进行转换

List<String> words = Arrays.asList("hello", "world");List<Integer> wordLengths = words.stream().map(String::length).collect(Collectors.toList());

flatMap()

对流中的每个元素进行转换,并将结果合并为一个流

List<List<String>> namesNested = Arrays.asList( Arrays.asList("Jeff", "Bezos"), Arrays.asList("Bill", "Gates"), Arrays.asList("Mark", "Zuckerberg"));List<String> namesFlatStream = namesNested.stream().flatMap(Collection::stream).collect(Collectors.toList());

distinct()

去除流中重复的元素

List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5, 2, 4, 1);List<Integer> distinctNumbers = numbers.stream().distinct().collect(Collectors.toList());

sorted()

对流中的元素进行排序

List<Integer> numbers = Arrays.asList(3, 2, 1, 4, 5);List<Integer> sortedNumbers = numbers.stream().sorted().collect(Collectors.toList());

peek()

对流中的每个元素执行特定的操作,通常用于调试

List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5);List<Integer> evenNumbers = numbers.stream().filter(x -> x % 2 == 0).peek(System.out::println).collect(Collectors.toList());

limit()

限制流中的元素数量

List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5);List<Integer> firstTwoNumbers = numbers.stream().limit(2).collect(Collectors.toList());

skip()

跳过流中的前若干个元素

List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5);List<Integer> lastThreeNumbers = numbers.stream().skip(2).collect(Collectors.toList());

forEach()

对流中的每个元素执行特定的操作

List<String> names = Arrays.asList("Alice", "Bob", "Charlie");names.stream().forEach(System.out::println);

reduce()

对流中的元素进行归约操作,返回一个值

List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5);int sum = numbers.stream().reduce(0, Integer::sum);

示例代码与注释:

代码语言:javascript
复制
import java.util.Arrays;
import java.util.Collection;
import java.util.List;
import java.util.stream.Collectors;

public class StreamDemo {

    public static void main(String[] args) {
        // 创建一个List对象
        List<String> words = Arrays.asList("hello", "world", "java", "stream");

        // 使用filter和collect方法过滤出长度大于4的单词
        List<String> filteredWords = words.stream()
                .filter(word -> word.length() > 4)
                .collect(Collectors.toList());
        System.out.println(filteredWords); // [world, stream]

        // 使用map和collect方法将单词转换为大写形式
        List<String> uppercaseWords = words.stream()
                .map(String::toUpperCase)
                .collect(Collectors.toList());
        System.out.println(uppercaseWords); // [HELLO, WORLD, JAVA, STREAM]

        // 使用flatMap和collect方法将多个List合并为一个List,并去重
        List<List<String>> nestedLists = Arrays.asList(
                Arrays.asList("hello", "world"),
                Arrays.asList("java", "stream"),
                Arrays.asList("hello", "java")
        );
        List<String> uniqueWords = nestedLists.stream()
                .flatMap(Collection::stream)
                .distinct()
                .collect(Collectors.toList());
        System.out.println(uniqueWords); // [hello, world, java, stream]

        // 使用sorted方法对List进行排序
        List<Integer> numbers = Arrays.asList(5, 2, 3, 1, 4);
        List<Integer> sortedNumbers = numbers.stream()
                .sorted()
                .collect(Collectors.toList());
        System.out.println(sortedNumbers); // [1, 2, 3, 4, 5]

        // 使用peek方法输出每个元素的值
        List<Integer> evenNumbers = numbers.stream()
                .filter(n -> n % 2 == 0)
                .peek(System.out::println)
                .collect(Collectors.toList());
        // 输出为:
        // 2
        // 4
        System.out.println(evenNumbers); // [2, 4]

        // 使用limit方法限制输出元素的数量
        List<Integer> firstThreeNumbers = numbers.stream()
                .limit(3)
                .collect(Collectors.toList());
        System.out.println(firstThreeNumbers); // [5, 2, 3]

        // 使用skip方法跳过前两个元素
        List<Integer> lastThreeNumbers = numbers.stream()
                .skip(2)
                .collect(Collectors.toList());
        System.out.println(lastThreeNumbers); // [3, 1, 4]

        // 使用forEach方法输出每个元素的值
        words.stream().forEach(System.out::println);
        // 输出为:
        // hello
        // world
        // java
        // stream

        // 使用reduce方法求List中所有元素的和
        int sum = numbers.stream()
                .reduce(0, Integer::sum);
        System.out.println(sum); // 15
    }
}

🔎4.Stream流的收集操作

以下是Java中Stream流的常用收集操作及示例:

操作

方法

示例

转化为List

collect(Collectors.toList())

List<String> list = Stream.of(“a”, “b”, “c”).collect(Collectors.toList());

转化为Set

collect(Collectors.toSet())

Set<String> set = Stream.of(“a”, “b”, “c”).collect(Collectors.toSet());

转化为Map

collect(Collectors.toMap(key, value))

Map<String, Integer> map = Stream.of(“a”, “aa”, “aaa”).collect(Collectors.toMap(Function.identity(), String::length));

转化为GroupingMap

collect(Collectors.groupingBy(key))

Map<Integer, List<String>> map = Stream.of(“a”, “b”, “aa”, “bb”, “aaa”, “bbb”).collect(Collectors.groupingBy(String::length));

转化为统计结果

collect(Collectors.summarizingInt/Long/Double)

IntSummaryStatics stats = Stream.of(1, 2, 3, 4, 5).collect(Collectors.summarizingInt(Integer::intValue));

PS:其中 key 代表作为Map的key的函数, value 代表作为Map的value的函数,可以是Lambda表达式或方法引用, Function.identity() 代表不改变元素的函数。

示例代码:

代码语言:javascript
复制
import java.util.*;
import java.util.stream.Collectors;

public class StreamCollect {
    public static void main(String[] args) {
        // 转化为List
        List<String> list = Stream.of("a", "b", "c").collect(Collectors.toList());
        System.out.println(list);   // [a, b, c]

        // 转化为Set
        Set<String> set = Stream.of("a", "b", "c").collect(Collectors.toSet());
        System.out.println(set);   // [a, b, c]

        // 转化为Map
        Map<String, Integer> map = Stream.of("a", "aa", "aaa").collect(Collectors.toMap(s -> s, String::length));
        System.out.println(map);   // {a=1, aa=2, aaa=3}

        // 转化为GroupingMap
        Map<Integer, List<String>> groupingMap = Stream.of("a", "b", "aa", "bb", "aaa", "bbb").collect(Collectors.groupingBy(String::length));
        System.out.println(groupingMap);   // {1=[a, b], 2=[aa, bb], 3=[aaa, bbb]}

        // 转化为统计结果
        IntSummaryStatistics stats = Stream.of(1, 2, 3, 4, 5).collect(Collectors.summarizingInt(Integer::intValue));
        System.out.println(stats);   // IntSummaryStatistics{count=5, sum=15, min=1, average=3.000000, max=5}
    }
}

🔎5.Stream流综合练习

假设有一个Person类,包含姓名、年龄、性别三个属性:

代码语言:javascript
复制
public class Person {
    private String name;
    private int age;
    private String gender;

    public Person(String name, int age, String gender) {
        this.name = name;
        this.age = age;
        this.gender = gender;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    public String getGender() {
        return gender;
    }

    public void setGender(String gender) {
        this.gender = gender;
    }

    @Override
    public String toString() {
        return "Person{" +
                "name='" + name + '\'' +
                ", age=" + age +
                ", gender='" + gender + '\'' +
                '}';
    }
}

现在需要对一个Person列表进行以下操作:

  1. 找出所有年龄大于18岁的人,按照年龄降序排列,只输出姓名和年龄
  2. 找出所有女性的平均年龄
  3. 找出所有男性的最小年龄
  4. 统计每个性别的人数

完整的代码如下:

代码语言:javascript
复制
import java.util.*;
import java.util.stream.Collectors;

public class StreamDemo {
    public static void main(String[] args) {
        List<Person> personList = new ArrayList<>();
        personList.add(new Person("张三", 23, "男"));
        personList.add(new Person("李四", 21, "男"));
        personList.add(new Person("王五", 19, "女"));
        personList.add(new Person("赵六", 25, "女"));
        personList.add(new Person("钱七", 17, "男"));
        personList.add(new Person("孙八", 30, "女"));

        // 找出所有年龄大于18岁的人,按照年龄降序排列,只输出姓名和年龄
        List<String> nameAndAge = personList.stream()
                .filter(person -> person.getAge() > 18)
                .sorted((p1, p2) -> p2.getAge() - p1.getAge())
                .map(person -> person.getName() + ":" + person.getAge())
                .collect(Collectors.toList());
        System.out.println("nameAndAge = " + nameAndAge);

        // 找出所有女性的平均年龄
        OptionalDouble femaleAverageAge = personList.stream()
                .filter(person -> person.getGender().equals("女"))
                .mapToInt(Person::getAge)
                .average();
        if (femaleAverageAge.isPresent()) {
            System.out.println("femaleAverageAge = " + femaleAverageAge.getAsDouble());
        } else {
            System.out.println("没有女性");
        }

        // 找出所有男性的最小年龄
        OptionalInt maleMinAge = personList.stream()
                .filter(person -> person.getGender().equals("男"))
                .mapToInt(Person::getAge)
                .min();
        if (maleMinAge.isPresent()) {
            System.out.println("maleMinAge = " + maleMinAge.getAsInt());
        } else {
            System.out.println("没有男性");
        }

        // 统计每个性别的人数
        Map<String, Long> genderCount = personList.stream()
                .collect(Collectors.groupingBy(Person::getGender, Collectors.counting()));
        System.out.println("genderCount = " + genderCount);
    }
}
本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2025-01-20,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 🚀一、可变参数
    • 🔎1.概念
    • 🔎2.作用
    • 🔎3.案例
    • 🔎4.注意事项
  • 🚀二、不可变集合
    • 🔎1.概念
    • 🔎2.作用
    • 🔎3.案例
    • 🔎4.注意事项
  • 🚀三、Stream流
    • 🔎1.Stream流的概述
    • 🔎2.Stream流的获取
    • 🔎3.Stream流的常用API
    • 🔎4.Stream流的收集操作
    • 🔎5.Stream流综合练习
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档