Java 8 Stream流:代码简洁之道

news2024/12/22 18:45:06

文章目录

  • 前言
  • 一、filter
  • 二、map
  • 三、mapToInt、mapToLong、mapToDouble
  • 四、flatMap
  • 五、flatMapToInt、flatMapToLong、flatMapToDouble
  • 六、distinct
  • 七、sorted
  • 八、peek
  • 九、limit
  • 十、forEach
  • 十一、forEachOrdered
  • 十二、toArray
  • 十三、reduce
  • 十四、collect
  • 十五、min、max
  • 十六、count
  • 十七、anyMatch、allMatch、noneMatch
  • 十八、findFirst、findAny
  • 十九、builder
  • 二十、of
  • 二十一、iterate
  • 二十二、generate
  • 二十三、concat
  • 总结


前言

想象一下,当你在编写一段复杂的代码时,突然有一种魔法💫可以让你的代码变得简洁又易读。
是不是很像科幻小说的情节?😄🎉
但是,Java 8的Stream流却能帮你实现这个梦想!✨
它就像一位技术大师,悄悄地走进了Java的大门,带来了编程世界的一次革命!💫✨
Stream流让我们能够以一种流畅的方式处理集合数据,解决了代码中循环和条件语句的臃肿问题。
想象一下,你不再需要写一堆循环来遍历数据,而是可以使用简洁的链式调用来完成各种操作。
不禁让人感叹,这简直就是程序员们的福音啊!🚀🌟
Stream流的魔力可不止于此!!!
它还可以让我们对数据进行筛选、排序、映射、归约等操作,就像在玩一场代码的魔法方块🧩,把数据进行各种变换和组合。
不仅如此,它还能让我们轻松处理大数据量,提高我们的开发效率。🚀🚀🚀
你可能会觉得,听起来好像有点夸张吧?💫
不过,我保证你一旦掌握了Stream流的技巧,就会爱不释手!就像拥有了一把魔法棒🧩,能够在代码的世界中释放出无穷的创造力。🎉
所以,亲爱的朋友们,如果你们还在为冗长的代码而苦恼,还在为难以理解的循环而犯愁,那就赶快加入我们的Stream流冒险队伍吧!🎉
通过本篇博客的指导,你将轻松掌握Stream流的诀窍,从而开启一段幽默有趣的编程之旅。😁🌈
准备好了吗?🌈🌈🌈
让我们一起笑着、学着、玩着,探索Stream流的代码简洁之道吧!
记住,Java 8 Stream流不仅仅是一段代码,更是一场奇幻冒险,让我们享受这一段令人愉快的编程之旅吧!🚀🚀🚀

在这里插入图片描述

一、filter

当涉及到数据处理和筛选时,filter() 方法是一个非常常用的方法。它可以用于过滤集合、数组或流中的元素,根据指定的条件只保留满足条件的元素,从而生成一个新的集合或流。

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

上述代码通过将集合转换为 Stream,然后在 Stream 上调用 filter() 方法,并提供一个谓词(Predicate)来指定过滤条件。最后使用 collect() 方法将满足条件的元素收集到一个新的集合中。

二、map

map() 方法是一个集合操作方法,用于对集合中的每个元素应用一个指定的函数,并将函数的返回值收集到一个新的集合中。它能够将一个集合转换为另一个集合,新集合中的元素个数与原集合相同,但元素的类型或值可能会发生变化。

List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5);
List<Integer> squaredNumbers = numbers.stream()
                                       .map(num -> num * num)
                                       .collect(Collectors.toList());

上述代码使用 Stream API,通过调用 map() 方法对集合中的每个元素应用一个函数,并将返回的结果收集到一个新的集合中。在示例中,使用 Lambda 表达式 num -> num * num 将每个数字平方,并将结果收集到 squaredNumbers 集合中。

三、mapToInt、mapToLong、mapToDouble

mapToInt() 是 Java 中专门用于处理基本数据类型的 Stream 接口的一个方法。它将 Stream 中的元素映射为 int 类型,并返回一个 IntStream,其中包含映射的结果。

List<String> strings = Arrays.asList("1", "2", "3", "4", "5");
IntStream intStream = strings.stream()
                             .mapToInt(Integer::parseInt);
intStream.forEach(System.out::println); // 输出 1 2 3 4 5

在上述示例中,使用 mapToInt(Integer::parseInt) 将字符串转换为相应的 int 数值。然后通过 forEach() 方法遍历 IntStream 中的每个元素,并打印出结果。

使用 mapToInt() 方法可以极大地简化在 Stream 中处理基本数据类型的逻辑,避免了自动装箱和拆箱的开销,并提供了更高效的处理方式。同时,还可以使用 IntStream 提供的丰富的方法来进行进一步的处理和操作。
mapToLong、mapToDouble以上相同

四、flatMap

flatMap() 方法是 Java 中用于处理嵌套集合的 Stream 接口的一个方法。它可以将嵌套的集合结构展平为一个扁平化的流,从而方便进行进一步的处理和操作。

List<List<Integer>> nestedList = Arrays.asList(
    Arrays.asList(1, 2),
    Arrays.asList(3, 4),
    Arrays.asList(5, 6)
);
Stream<Integer> flattenedStream = nestedList.stream()
                                            .flatMap(Collection::stream);
flattenedStream.forEach(System.out::println); // 输出 1 2 3 4 5 6

在上述示例中,nestedList 是一个包含多个嵌套列表的集合。通过使用 flatMap(Collection::stream),将每个嵌套列表转换为一个 Stream,然后将所有的 Stream 连接起来形成一个扁平化的流。最后使用 forEach() 方法遍历扁平化后的流并打印元素。

使用 flatMap() 方法可以方便地处理包含嵌套集合的数据结构,并将其展开为一个扁平化的流,使后续的处理更加便捷和灵活。这个方法在处理多层嵌套的数据结构时特别有用,可以避免繁琐的嵌套循环操作。

五、flatMapToInt、flatMapToLong、flatMapToDouble

flatMapToInt() 是 Java 中专门用于处理基本数据类型的扁平化流的 Stream 接口的一个方法。它将 Stream 中的元素映射为 IntStream 类型,并将所有的 IntStream 连接起来形成一个扁平化的流。

List<List<Integer>> nestedList = Arrays.asList(
    Arrays.asList(1, 2),
    Arrays.asList(3, 4),
    Arrays.asList(5, 6)
);
IntStream flattenedIntStream = nestedList.stream()
                                         .flatMapToInt(innerList -> innerList.stream().mapToInt(Integer::intValue));
flattenedIntStream.forEach(System.out::println); // 输出 1 2 3 4 5 6

在上述示例中,nestedList 是一个包含多个嵌套列表的集合。通过使用 flatMapToInt(innerList -> innerList.stream().mapToInt(Integer::intValue)),将每个嵌套列表转换为一个 IntStream,然后将所有的 IntStream 连接起来形成一个扁平化的流。最后使用 forEach() 方法遍历扁平化后的流并打印元素。

使用 flatMapToInt() 方法可以方便地处理包含基本数据类型的嵌套集合,并将其展开为一个扁平化的流,使后续的处理更加便捷和灵活。这个方法在处理多层嵌套的数据结构时特别有用,可以避免繁琐的嵌套循环操作,并能够更高效地处理基本数据类型。
flatMapToLong、flatMapToDouble以上相同

六、distinct

distinct() 是 Java 中 Stream 接口的一个方法,用于去除流中重复的元素,返回一个由不同元素组成的新流。
distinct() 方法返回的新流中,元素的顺序保持与原始流中的顺序相同。它使用元素的 equals() 方法来判断是否为重复元素,因此要确保元素正确实现了 equals() 方法。

List<Integer> numbers = Arrays.asList(1, 2, 2, 3, 3, 3, 4, 5, 5);
Stream<Integer> distinctStream = numbers.stream().distinct();
distinctStream.forEach(System.out::println); // 输出 1 2 3 4 5

在上述示例中,我们有一个包含重复元素的列表 numbers。通过使用 distinct() 方法,我们获取到一个新流 distinctStream,其中去除了重复的元素。最后使用 forEach() 方法处理新流,并打印每个元素。

注意,distinct() 方法依赖于元素的 equals() 方法来判断是否为重复元素。如果元素没有正确重写 equals() 方法,可能无法正确去除重复元素,返回的流中仍会包含重复的元素。

使用 distinct() 方法可以方便地对流中的元素进行去重操作,使得后续的处理更加准确和高效。

七、sorted

sorted() 是 Java 中 Stream 接口的一个方法,用于对流进行排序操作。它返回一个新的流,其中的元素按照自然顺序或根据指定的比较器进行排序。

List<Integer> numbers = Arrays.asList(5, 3, 1, 4, 2);
Stream<Integer> sortedStream = numbers.stream().sorted();
sortedStream.forEach(System.out::println); // 输出 1 2 3 4 5

在上述示例中,我们有一个包含整数的列表 numbers。通过使用 sorted() 方法,我们获取到一个新的流 sortedStream,其中的元素按照自然顺序进行排序。最后使用 forEach() 方法处理新流,并打印每个元素。

class Student {
    private String name;
    private int age;
    
    public Student(String name, int age) {
        this.name = name;
        this.age = age;
    }
    
    // getter 和 setter 方法省略
    
    @Override
    public String toString() {
        return name + " - " + age;
    }
}

List<Student> students = new ArrayList<>();
students.add(new Student("Alice", 22));
students.add(new Student("Bob", 20));
students.add(new Student("Charlie", 21));

// 按照年龄升序排序
students.stream()
        .sorted((s1, s2) -> Integer.compare(s1.getAge(), s2.getAge()))
        .forEach(System.out::println);

// 按照名称长度降序排序
students.stream()
        .sorted((s1, s2) -> Integer.compare(s2.getName().length(), s1.getName().length()))
        .forEach(System.out::println);

在上述示例中,有一个包含学生对象的列表 students。首先,通过传入一个比较器匿名类 (s1, s2) -> Integer.compare(s1.getAge(), s2.getAge()),使用 sorted() 方法将学生对象按照年龄升序进行排序。然后,传入另一个比较器 (s1, s2) -> Integer.compare(s2.getName().length(), s1.getName().length()),使用 sorted() 方法将学生对象按照名称长度降序进行排序。

通过定制的比较器,我们可以根据不同的排序规则和属性进行排序操作。

八、peek

peek() 是 Java 中 Stream 接口的一个中间操作方法,用于在流的处理过程中执行额外的操作,而不会改变流中的元素。

List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5);
numbers.stream()
       .peek(System.out::println) // 打印每个元素
       .map(n -> n * 2) // 将每个元素乘以2
       .forEach(System.out::println); // 打印处理后的元素

在上述示例中,我们有一个包含整数的列表 numbers。通过使用 stream() 方法获取流,然后使用 peek() 方法提供一个消费者函数,对每个元素进行打印操作。在打印完元素后,使用 map() 方法将每个元素乘以2,最后使用 forEach() 方法打印处理后的元素。

需要注意的是,peek() 方法并不是用于修改流中的元素,而是通过回调函数执行额外的操作。它返回的仍然是原始的流,可以继续进行其他的中间操作或终端操作。

peek() 方法常用于调试、记录中间状态、查看流中的元素等场景。可以结合其他的流操作一起使用,提供更灵活的流处理。但是需要注意,它不应该用于具有副作用的操作,比如修改可变状态,因为其结果是不可预测的。

九、limit

limit() 是 Java 中 Stream 接口的一个中间操作方法,用于限制流中元素的数量,返回一个包含最多指定数量元素的新流。

List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5);
numbers.stream()
       .limit(3) // 限制最多3个元素
       .forEach(System.out::println); // 打印限制后的元素

在上述示例中,我们有一个包含整数的列表 numbers。通过使用 stream() 方法获取流,然后使用 limit() 方法限制最多只能获取3个元素。最后使用 forEach() 方法打印限制后的元素。

limit() 方法对于在大型流中处理前几个元素非常有用,可以提高性能和节省资源。

需要注意的是,limit() 方法会在满足指定数量的元素之后截断流,因此如果流中元素数量少于指定的最大数量,那么限制后的流将包含所有元素。

总结来说,limit() 方法可以用于限制流中元素数量,提供了一种简单有效的方式来处理大型数据流或控制处理的范围。

十、forEach

forEach() 是 Java 中 Stream 接口的一个终端操作方法,用于对流中的每个元素执行指定的操作。

List<String> names = Arrays.asList("Alice", "Bob", "Charlie");
names.stream()
     .forEach(System.out::println); // 打印每个元素

在上述示例中,我们有一个包含字符串的列表 names。通过使用 stream() 方法获取流,然后使用 forEach() 方法传入一个消费者函数来打印流中的每个元素。

forEach() 方法会逐个处理流中的元素,并对每个元素执行指定的操作。它是一个终端操作,表示流的处理结束,因此在调用 forEach() 方法之后不能再对流进行其他操作。

需要注意的是,forEach() 并不保证元素的处理顺序,它可能是并行执行的。如果需要按照特定的顺序处理元素,可以考虑使用 forEachOrdered() 方法。

总结来说,forEach() 方法是一个简单而方便的方式,在流中的每个元素上执行特定的操作,比如打印、记录或其他自定义操作。它是一个终端操作,用于结束流的处理并执行最终操作。

十一、forEachOrdered

forEachOrdered() 是 Java 中 Stream 接口的一个终端操作方法,用于对流中的每个元素按照顺序执行指定的操作。
与 forEach() 方法不同的是,forEachOrdered() 方法会保证按照流的遍历顺序逐个处理流中的元素,而不管流是否是并行执行的。这种保证是通过对流进行合并和排序来实现的。

List<String> names = Arrays.asList("Alice", "Bob", "Charlie");
names.stream()
     .forEachOrdered(System.out::println); // 按顺序打印每个元素

在上述示例中,我们有一个包含字符串的列表 names。通过使用 stream() 方法获取流,然后使用 forEachOrdered() 方法传入一个消费者函数来按照顺序打印流中的每个元素。

forEachOrdered() 方法保证按照流的遍历顺序执行操作,而不管流是否是并行执行的。这对于确保按照原始顺序处理元素非常有用,特别是在并行流中。

需要注意的是,forEachOrdered() 是一个终端操作,表示流的处理结束,因此在调用该方法之后不能再对流进行其他操作。

总结来说,forEachOrdered() 方法是一个保证按顺序处理流中元素的方式,在流中的每个元素上执行特定的操作。与 forEach() 方法相比,它提供了对于并行执行的支持和顺序保证。

十二、toArray

toArray() 是 Java 中 Stream 接口的一个终端操作方法,用于将流中的元素转换为数组。
toArray() 方法将流中的元素按照流的遍历顺序转换为一个 Object 类型的数组,并返回该数组。
以下是使用 toArray() 方法的示例:

List<String> colors = Arrays.asList("Red", "Green", "Blue");
Object[] array = colors.stream()
                      .toArray();

在上述示例中,我们有一个包含字符串的列表 colors。通过使用 stream() 方法获取流,然后使用 toArray() 方法将流中的元素转换为一个 Object 类型的数组。
需要注意的是,toArray() 方法返回的是一个包含流中所有元素的数组,数组的元素类型为 Object。如果希望得到特定类型的数组,可以使用带有类型参数的 toArray() 方法,如下所示:

String[] array = colors.stream()
                       .toArray(String[]::new);

在上述示例中,我们使用 toArray(String[]::new),该方法会将流中的元素转换为一个 String 类型的数组,并返回该数组。

总结来说,toArray() 方法用于将流中的元素转换为数组。它提供了一种方便的方式来获取流中的元素集合,并以数组的形式进行处理或传递给其他方法。

十三、reduce

reduce() 是 Java 中 Stream 接口的一个终端操作方法,用于将流中的元素按照指定的操作进行归约(reduce)。
reduce() 方法使用指定的二元操作对流中的元素进行逐个归约,返回一个 Optional 对象,该对象包含归约的结果。如果流为空,则返回一个空的 Optional。
以下是使用 reduce() 方法的示例:

List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5);
Optional<Integer> sum = numbers.stream()
                               .reduce((a, b) -> a + b);

在上述示例中,我们有一个包含整数的列表 numbers。通过使用 stream() 方法获取流,然后使用 reduce() 方法传入一个对两个整数进行相加的二元操作 (a, b) -> a + b。

reduce() 方法将流中的元素按照指定的二元操作进行归约,得到一个结果。在本例中,我们将列表中的整数进行求和的归约操作。

reduce() 方法返回一个 Optional 对象,因为流可能为空。可以使用 Optional 的方法来获取归约的结果,如下所示:

int result = sum.orElse(0); // 获取归约的结果,如果为空则返回默认值 0

在上述示例中,我们使用 orElse(0) 方法从 Optional 对象中获取归约的结果,如果为空则返回默认值 0。

除了接受一个二元操作的 reduce() 方法,还有其他重载方法可以接受初始值和一个三元操作,更加灵活地进行归约的操作。

总结来说,reduce() 方法用于将流中的元素按照指定的操作进行归约。它提供了一种简单而强大的方式来处理流中的元素并生成一个结果。

十四、collect

collect() 是 Java 中 Stream 接口的一个终端操作方法,用于将流中的元素收集到一个可变容器或集合中。
Collector 是一个用于描述流元素收集过程的接口,其中包含了用于创建结果容器、收集元素和合并部分结果的方法。

以下是使用 collect() 方法的示例:

List<String> colors = Arrays.asList("Red", "Green", "Blue");
List<String> collectedList = colors.stream()
                                   .collect(Collectors.toList());

在上述示例中,我们有一个包含字符串的列表 colors。通过使用 stream() 方法获取流,然后使用 collect() 方法传入 Collectors.toList(),它是一个用于收集元素到列表中的内置收集器。

collect() 方法将流中的元素按照指定的收集器进行收集,返回收集后的结果。在本例中,我们将元素收集到一个列表中。

除了 Collectors.toList(),Java 还提供了其他内置的收集器,如 toSet()(收集到集合)、toMap()(收集到映射)、joining()(连接为字符串)等。

此外,还可以通过自定义 Collector 的方式进行个性化的集合操作,例如自定义结果容器、元素收集和结果合并的逻辑。

总结来说,collect() 方法用于将流中的元素收集到一个可变容器或集合中。它提供了一种灵活且强大的方式来处理流中的元素,并生成最终的收集结果。

十五、min、max

min() 和 max() 是 Java 中 Stream 接口的终端操作方法,用于找到流中的最小值和最大值。
min() 和 max() 是 Java 中 Stream 接口的终端操作方法,用于找到流中的最小值和最大值。
以下是使用 min() 和 max() 方法的示例:

List<Integer> numbers = Arrays.asList(2, 5, 1, 3, 4);
Optional<Integer> min = numbers.stream()
                               .min(Comparator.naturalOrder());

Optional<Integer> max = numbers.stream()
                               .max(Comparator.naturalOrder());

在上述示例中,我们有一个包含整数的列表 numbers。通过使用 stream() 方法获取流,在 min() 或 max() 方法中传入 Comparator.naturalOrder(),它是一个自然排序的比较器,即比较元素的自然顺序。

min() 方法返回一个 Optional 对象,包含列表中的最小元素。在本例中,返回的 Optional 包含值 1。

max() 方法同样返回一个 Optional 对象,包含列表中的最大元素。在本例中,返回的 Optional 包含值 5。

可以使用 Optional 的方法来获取最小/最大元素,如下所示:

int minValue = min.orElse(0); // 获取最小值,如果为空则返回默认值 0
int maxValue = max.orElseThrow(); // 获取最大值,如果为空则抛出异常

在上述示例中,我们分别使用 orElse(0) 和 orElseThrow() 方法从 Optional 对象中获取最小/最大元素。

如果想要自定义比较器来进行比较,可以实现自己的 Comparator 接口。

总结来说,min() 和 max() 方法用于在流中找到最小值和最大值。它们提供了一种便捷的方式来找到流元素中的极值,并以 Optional 的形式返回结果。

十六、count

count() 是 Java 中 Stream 接口的一个终端操作方法,用于计算流中元素的个数。
以下是使用 count() 方法的示例:

List<String> colors = Arrays.asList("Red", "Green", "Blue");
long count = colors.stream()
                   .count();

在上述示例中,我们有一个包含字符串的列表 colors。通过使用 stream() 方法获取流,然后使用 count() 方法计算流中元素的个数。

count() 方法返回一个 long 值,表示流中元素的个数。在本例中,返回的值为 3。

需要注意的是,count() 方法是一个终端操作,一旦调用了 count() 方法,流就会被消费一次,无法再次使用。

另外,对于大型或无界的流,count() 方法可能会消耗较长的时间,因为它需要遍历整个流来计算元素的个数。

总结来说,count() 方法用于计算流中元素的个数。它提供了一种简便的方式来获取流的大小,对于统计和判断流是否为空等场景非常有用。

十七、anyMatch、allMatch、noneMatch

anyMatch(), allMatch() 和 noneMatch() 是 Java 中 Stream 接口的终端操作方法,用于检查流中的元素是否满足特定的条件。

anyMatch() 方法用于检查至少有一个元素满足给定条件。
allMatch() 方法用于检查所有元素是否都满足给定条件。
noneMatch() 方法用于检查没有元素满足给定条件。
这些方法都接受一个 Predicate 参数,表示用于检查元素的条件。Predicate 是一个函数式接口,用于表示一个接受一个参数并返回布尔值的函数。

以下是使用 anyMatch()、allMatch() 和 noneMatch() 方法的示例:

List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5);

boolean anyMatchResult = numbers.stream()
                                .anyMatch(n -> n % 2 == 0);

boolean allMatchResult = numbers.stream()
                                .allMatch(n -> n > 0);

boolean noneMatchResult = numbers.stream()
                                 .noneMatch(n -> n > 5);

在上述示例中,我们有一个包含整数的列表 numbers。通过使用 stream() 方法获取流,并在 anyMatch()、allMatch()、noneMatch() 方法中提供相应的条件。

anyMatch() 方法检查流中是否有至少一个元素满足给定条件。在本例中,返回的结果为 true,因为列表中存在一个偶数(2)满足条件。

allMatch() 方法检查流中的所有元素是否都满足给定条件。在本例中,返回的结果为 true,因为列表中的所有元素都大于 0。

noneMatch() 方法检查流中是否没有元素满足给定条件。在本例中,返回的结果为 true,因为列表中没有大于 5 的元素。

这些方法返回一个布尔值,表示检查的结果是否满足给定的条件。

需要注意的是,以上方法都是短路操作,即一旦确定结果是 true 或 false,就会立即停止遍历剩余的元素。

总结来说,anyMatch()、allMatch() 和 noneMatch() 方法用于检查流中的元素是否满足给定的条件。它们提供了一种简洁的方式来进行流元素的条件判断,非常适用于筛选和验证的场景。

十八、findFirst、findAny

findFirst() 和 findAny() 是 Java 中 Stream 接口的终端操作方法,用于在流中查找满足给定条件的元素。
findFirst() 方法用于查找流中的第一个满足条件的元素。
findAny() 方法用于查找流中的任意一个满足条件的元素。
以下是使用 findFirst() 和 findAny() 方法的示例:

List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5);

Optional<Integer> first = numbers.stream()
                                 .findFirst();

Optional<Integer> any = numbers.stream()
                               .findAny();

在上述示例中,我们有一个包含整数的列表 numbers。通过使用 stream() 方法获取流,并在 findFirst()、findAny() 方法中调用。

findFirst() 方法返回流中的第一个满足条件的元素。在本例中,返回的 Optional 包含元素 1。

findAny() 方法返回流中的任意一个满足条件的元素。在本例中,返回的 Optional 包含元素 1,因为在列表中满足条件的元素是唯一的。

需要注意的是,这两个方法都是短路操作,一旦找到满足条件的元素,就会立即停止遍历剩余的元素。

对于有序的流,findFirst() 方法通常返回流中的第一个元素,而 findAny() 方法则可以返回任意一个满足条件的元素。

对于并行流(parallel stream),对于非有序的流,findAny() 可能会比 findFirst() 更快,因为它可以在多个并行子流中寻找满足条件的元素。

总结来说,findFirst() 和 findAny() 方法用于在流中查找满足条件的元素。它们返回一个 Optional 对象,表示可能存在或可能为空的结果。在需要查找特定元素或仅需任意满足条件的元素时,这些方法非常有用。

十九、builder

在Java中,"builder"是一种设计模式,用于创建复杂对象的构造器。Builder模式允许我们逐步构建对象,并可以根据需要自定义对象的属性。

Builder模式通常包含一个用于设置属性的builder类,以及一个用于构建最终对象的builder方法链。通过使用builder模式,我们可以避免编写冗长的构造函数并处理多个可选参数。

以下是使用Builder模式的示例:

public class Person {
    private String name;
    private int age;
    private String address;

    private Person(Builder builder) {
        this.name = builder.name;
        this.age = builder.age;
        this.address = builder.address;
    }

    public String getName() {
        return name;
    }

    public int getAge() {
        return age;
    }

    public String getAddress() {
        return address;
    }

    public static class Builder {
        private String name;
        private int age;
        private String address;

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

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

        public Builder setAddress(String address) {
            this.address = address;
            return this;
        }

        public Person build() {
            return new Person(this);
        }
    }
}

在上述示例中,我们定义了一个Person类,并使用内部静态类Builder作为Person类的构造器。Person类具有私有的构造函数,只能通过Builder来构建对象。

Builder类提供了一组用于设置属性的方法(setName,setAge,setAddress),并通过链式调用返回Builder对象。最后,Builder类提供了一个build方法,该方法利用Builder对象的属性创建一个Person对象。

通过使用Builder模式,我们可以以更清晰、简洁的方式构建对象:

Person person = new Person.Builder()
                        .setName("John")
                        .setAge(25)
                        .setAddress("123 Main St")
                        .build();

在这个示例中,我们使用Builder模式逐步构建Person对象,设置了name、age和address属性,并通过build方法创建最终的Person对象。

通过使用Builder模式,我们可以更容易地创建具有多个可选属性的对象,并且不需要在构造函数中使用大量的参数。这提供了更好的灵活性和可读性。

二十、of

在Java 8的Stream API中,"of"方法用于创建一个由指定元素组成的流。

Stream<Integer> numbers = Stream.of(1, 2, 3, 4, 5);

在这个示例中,我们使用Stream的"of"方法创建了一个包含整数元素的流。

二十一、iterate

在Java中,iterate 是Stream API中的一个静态方法,用于创建一个按照指定规则迭代生成元素的流。

iterate 方法接受两个参数:初始值和迭代函数。它会根据迭代函数对初始值进行重复应用,生成一个无限流。

以下是 iterate 方法的示例:

Stream.iterate(1, n -> n + 1)
      .limit(5)
      .forEach(System.out::println);

在上述示例中,我们使用 iterate 方法创建一个从1开始的自增序列流。迭代函数 n -> n + 1 将初始值加1,然后再将结果作为下一次迭代的初始值。

通过使用 limit 方法,我们限制流的大小,只取前5个元素。最后,使用 forEach 方法打印每个元素。

输出结果为

1
2
3
4
5

需要注意的是,iterate 方法生成的是无限流。如果不使用 limit 方法或其他中止操作,流将无限地生成元素。

除了上述示例中的递增序列,我们还可以根据需要使用不同的迭代函数生成不同的序列。

例如,创建一个斐波那契数列的流:

Stream.iterate(new int[]{0, 1}, fib -> new int[]{fib[1], fib[0] + fib[1]})
      .limit(10)
      .forEach(fib -> System.out.print(fib[0] + " "));

输出结果为:

0 1 1 2 3 5 8 13 21 34

在这个示例中,我们使用一个整数数组来表示每个斐波那契数列元素。迭代函数会根据前两个元素的值计算出下一个元素。

总结来说,iterate 方法允许我们根据指定的迭代函数生成无限流。通过结合使用流的其他中止操作,我们可以对生成的元素进行限制、过滤、映射等操作。这样我们就可以便捷地生成不同规则的序列或重复数据。

二十二、generate

在Java中,generate 是Stream API中的一个静态方法,用于创建一个由指定生成函数生成元素的流。

generate 方法接受一个无参的生成函数作为参数,并通过重复调用该函数来生成流的元素。生成函数不接受任何输入参数,只返回一个新的元素。

以下是 generate 方法的示例:

Stream.generate(() -> "Hello")
      .limit(5)
      .forEach(System.out::println);

在上述示例中,我们使用 generate 方法创建了一个由字符串 “Hello” 组成的流。生成函数 () -> “Hello” 在每次调用时都返回字符串 “Hello”。

通过使用 limit 方法,我们限制流的大小,只取前5个元素。最后,使用 forEach 方法打印每个元素。

输出结果为:

Hello
Hello
Hello
Hello
Hello

需要注意的是,generate 方法生成的是无限流。如果不使用 limit 方法或其他中止操作,流将无限地生成元素。

除了简单地生成固定值的流,我们还可以根据需要生成更复杂的元素。

例如,生成一个随机整数的流:

Stream.generate(() -> new Random().nextInt(100))
      .limit(5)
      .forEach(System.out::println);

输出结果为:

76
41
62
89
14

在这个示例中,我们使用生成函数 () -> new Random().nextInt(100) 创建一个返回随机整数 (0到99之间) 的流。

总结来说,generate 方法允许我们根据指定的生成函数生成流。通过结合使用流的其他中止操作,我们可以对生成的元素进行限制、过滤、映射等操作。这样我们就可以便捷地生成根据不同规则生成元素的流。

二十三、concat

在Java中,concat 是Stream API中的一个静态方法,用于合并两个流。

concat 方法接受两个流作为参数,并返回一个新的流,其中包含两个输入流中的所有元素。

以下是 concat 方法的示例:

Stream<Integer> stream1 = Stream.of(1, 2, 3);
Stream<Integer> stream2 = Stream.of(4, 5, 6);

Stream<Integer> combinedStream = Stream.concat(stream1, stream2);
combinedStream.forEach(System.out::println);

在上述示例中,我们创建了两个整数流 stream1 和 stream2,分别包含数字 1 到 3 和 4 到 6。

然后,我们使用 concat 方法合并这两个流,并将结果赋给了新的流 combinedStream。

最后,我们通过 forEach 方法遍历并打印合并后的流中的所有元素。

输出结果为:

1
2
3
4
5
6

需要注意的是,concat 方法将两个流合并成一个新的流,并保持了元素的顺序。

除了合并两个流之外,concat 方法还可以与其他流进行串联,以实现更多的组合。

例如,串联多个流:

Stream<Integer> stream1 = Stream.of(1, 2, 3);
Stream<Integer> stream2 = Stream.of(4, 5, 6);
Stream<Integer> stream3 = Stream.of(7, 8, 9);

Stream<Integer> combinedStream = Stream.concat(Stream.concat(stream1, stream2), stream3);
combinedStream.forEach(System.out::println);

在这个示例中,我们将三个整数流 stream1、stream2 和 stream3 串联起来,得到一个包含所有元素的新流。

输出结果为:

1
2
3
4
5
6
7
8
9

总结来说,concat 方法允许我们合并两个流来创建一个包含两个输入流中所有元素的新流。它提供了一种简便的方式来组合多个流。

总结

@作者:加辣椒了吗?
简介:憨批大学生一枚,喜欢在博客上记录自己的学习心得,也希望能够帮助到你们!
在这里插入图片描述

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

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

相关文章

mysql(二) 索引-基础知识

继续整理复习、我以我的理解和认知来整理 "索引" 会通过 文 和 图 来展示。 文&#xff1a; 基本概念知识&#xff08;mysql 的索引分类、实现原理&#xff09; 图&#xff1a; 画B树等 MySQL官方对索引的定义是&#xff1a;索引&#xff08;Index&#xff09;是帮…

记录--虚拟 DOM 和实际 DOM 有何不同?

这里给大家分享我在网上总结出来的一些知识&#xff0c;希望对大家有所帮助 前言 本文我们会先聊聊 DOM 的一些缺陷&#xff0c;然后在此基础上介绍虚拟 DOM 是如何解决这些缺陷的&#xff0c;最后再站在双缓存和 MVC 的视角来聊聊虚拟 DOM。理解了这些会让你对目前的前端框架有…

第四章 HL7 架构和可用工具 - 查看数据结构

文章目录 第四章 HL7 架构和可用工具 - 查看数据结构查看数据结构查看代码表使用自定义架构编辑器 第四章 HL7 架构和可用工具 - 查看数据结构 查看数据结构 当单击“数据结构”列中的名称时&#xff0c;InterSystems 会显示该数据结构中的所有字段。这是 HL7 数据结构页面。…

影视行业案例 | 燕千云助力大地影院集团搭建智能一体化IT服务管理平台

影视行业过去三年受新冠肺炎疫情影响&#xff0c;经历了一定程度的冲击和调整&#xff0c;但也展现出了强大的韧性和潜力。2023年中国影视产业规模可能达到2600亿元左右&#xff0c;同比增长11%左右。影视行业的发展趋势主要表现在内容创新、模式创新和产业融合三个方面&#x…

第八章:将自下而上、自上而下和平滑性线索结合起来进行弱监督图像分割

0.摘要 本文解决了弱监督语义图像分割的问题。我们的目标是在仅给出与训练图像关联的图像级别对象标签的情况下&#xff0c;为新图像中的每个像素标记类别。我们的问题陈述与常见的语义分割有所不同&#xff0c;常规的语义分割假设在训练中可用像素级注释。我们提出了一种新颖的…

PSP - MMseqs2 编译最新版本源码 (14-7e284) 支持 MPI 功能 MSA 快速搜索

欢迎关注我的CSDN&#xff1a;https://spike.blog.csdn.net/ 本文地址&#xff1a;https://spike.blog.csdn.net/article/details/131966061 MPI (Message Passing Interface) 是用于并行计算的标准化和可移植的消息传递接口&#xff0c;可以在分布式内存的多台计算机上运行并行…

操作系统、人工智能、芯片和其它

最近出差一段时间&#xff0c;听到一些事&#xff0c;看到一些事&#xff0c;说点个人观感。有些话可能不好听&#xff0c;还希望不要被平台和谐。   从一位现在微软工作的前同事处得来的消息&#xff0c;微软下一代操作系统Windows 12将深度集成AI&#xff0c;如果再加上的它…

彻底搞懂CPU的特权等级

x86 处理器中,提供了4个特权级别:0,1,2,3。数字越小,特权级别越高! 一般来说,操作系统是的重要性、可靠性是最高的,需要运行在 0 特权级; 应用程序工作在最上层,来源广泛、可靠性最低,工作在 3 特权级别。 中间的1 和 2 两个特权级别,一般很少使用。 理论上来讲,…

redis到底几个线程?

通常我们说redis是单线程指的是从接收客户端请求->解析请求->读写->响应客户端这整个过程是由一个线程来完成的。这并不意味着redis在任何场景、任何版本下都只有一个线程 为何用单线程处理数据读写&#xff1f; 内存数据储存已经很快了 redis相比于mysql等数据库是…

集合---list接口及实现类

一、list概述 1、list接口概述 List接口继承自Collection接口&#xff0c;是单列集合的一一个重要分支&#xff0c;我们习惯性地会将实现了 List接口的对象称为List集合。在List集合中允许出现重复的元素&#xff0c;所有的元素是以一种线性方 式进行有序存储的&#xff0c;在…

在linux中怎样同时运行三个微服务保证退出时不会终止

前言 1.maven中打jar包 使用插件打包,必须在pom.xml中添加插件,否则不能在linux中编译运行 <build><plugins><plugin><groupId>org.springframework.boot</groupId><artifactId>spring-boot-maven-plugin</artifactId><version&g…

RISC-V公测平台发布 · 第一个WEB Server “Hello RISC-V world!”

RISC-V公测平台Web Server地址&#xff1a;http://175.8.161.253:8081 一、前言 Web Server是互联网应用的基础设施&#xff0c;无论是用户访问网站&#xff0c;还是后端服务提供商和开发者构建各种应用程序&#xff0c;Web Server都在其中扮演着至关重要的角色。 显而易见…

甄品焕新 | 链接上下游企业服务协同,改变服务获取方式

文/玉娇龙 本文字数&#xff1a;3500&#xff5c;预计3分钟读完 使用燕千云上下游服务管理&#xff0c;你可以统一管理IT服务供应商、业务经销商、客户等业务伙伴的服务往来&#xff0c;将企业与上下游公司之间的工单服务往来进行统一管理、共享与升级&#xff0c;实现服务共享…

jmeter接口测试、压力测试简单实现

jmeter测试的组件执行顺序&#xff1a; 测试计划—>线程组—>配置元件—>前置处理器—>定时器—>逻辑控制器—>取样器—>后置处理器—>断言—>监听器 组件的作用范围&#xff1a; 同级组件同级组件下的子组件父组件 目前市面上的三类接口 1、基…

netty 809协议

netty 809协议 目录概述需求&#xff1a; 设计思路实现思路分析1.netty 809 协议2.概念代码 参考资料和推荐阅读 Survive by day and develop by night. talk for import biz , show your perfect code,full busy&#xff0c;skip hardness,make a better result,wait for chan…

ad+硬件每日学习十个知识点(15)23.7.26 (逻辑器件、拉电流和灌电流、OC门和OD门、总线保持)

文章目录 1.逻辑器件介绍2.什么是总线缓冲器&#xff1f;3.逻辑器件按功能分类4.逻辑器件按工艺分类&#xff08;目前主要用CMOS逻辑&#xff09;5.什么是总线保持&#xff1f;6.逻辑电平7.两个逻辑器件互连&#xff0c;需要满足什么要求&#xff1f;8.什么是推挽&#xff0c;什…

关于自签名证书授权后在哪儿看

目录 firefox可以看到 chrome and edge firefox可以看到 chrome and edge 只能从打开的网站左上角进入

读《全球科技通史》总结——历史总在重演,科技永远向前

今天和大家分享一下吴军老师的《全球科技通史》。大部分人谈到历史的时候&#xff0c;关注的是国家的兴衰、王朝的更替&#xff0c;往往忽视了科技的力量。“文津图书奖”得主吴军博士&#xff0c;从科技视角串联历史&#xff0c;首次以能量和信息两条主线&#xff0c;系统阐述…

【Docker】Docker相关基础命令

目录 一、Docker服务相关命令 1、启动docker服务 2、停止docker服务 3、重启docker服务 4、查看docker服务状态 5、开机自启动docker服务 二、Images镜像相关命令 1、查看镜像 2、拉取镜像 3、搜索镜像 4、删除镜像 三、Container容器相关命令 1、创建容器 2、查…

ad+硬件每日学习十个知识点(9)23.7.20

文章目录 1.正点原子fpga开拓者无gui检查项目2.排针连接器A2541WR-XP-2P3.肖特基二极管反接在LDO的输出端&#xff0c;是什么用&#xff1f;4.在AD中如何实现批量元器件的移动&#xff1f;5.在PCB中&#xff0c;如何让元器件以任意角度旋转&#xff1f;6.接口设计都要做静电防护…