Java8 Stream详解及创建流方法使用示例(二)

        本章介绍Stream 创建流的操作:创建流指的是将一个集合或其他数据源转换为 Stream 流对象的过程。通常情况下,我们可以使用 Stream 类的静态方法来创建流对象,如 Stream.of()、Collections.stream() 等。这些方法将返回一个 Stream 流对象,该对象可用于对数据进行各种操作。下面是一些常用的创建流的方法。Java8 Stream详解及中间操作创建方法使用示例(一)

  1. of(T... values):创建一个由指定元素组成的流。
  2. empty():创建一个空的流。
  3. generate(Supplier s):创建一个无限流,每次调用 get() 方法都会生成新的数据。
  4. iterate(T seed, UnaryOperator f):创建一个无限流,在每次迭代时都会应用指定的函数。
  5. concat(Stream a, Stream b):创建一个包含两个流的顺序流,先是流 a,再是流 b。
  6. builder():创建一个用于构建链式操作的 Builder 对象。
  7. ofNullable(T t):创建一个包含零个或一个元素的流,元素为指定对象(可以为 null)。
  8. range(int startInclusive, int endExclusive):创建一个包含从 startInclusive 开始(含)到 endExclusive 结束(不含)的整数序列流。
  9. rangeClosed(int startInclusive, int endInclusive):创建一个包含从 startInclusive 开始(含)到 endInclusive 结束(含)的整数序列流。

Stream创建流的方法详细介绍

of(T... values)

Stream的of(T... values)方法是一个静态方法,用于创建一个包含指定元素的顺序Stream对象。

具体用法如下:

  1. 调用of(T... values)方法并传入一个或多个元素。
  2. 该方法将返回包含指定元素的Stream对象。

例如,以下代码演示了如何使用of()方法创建一个包含多个元素的Stream对象:

Stream stream = Stream.of(1, 2, 3, 4, 5);

上述代码将创建一个包含整数1到5的Stream对象。可以根据需要使用该流进行后续操作,例如过滤、映射、排序等操作。

of(T t)

Stream的of(T t)方法是一个静态方法,用于创建一个包含单个元素的顺序Stream对象。

具体用法如下:

  1. 调用of(T t)方法并传入一个元素。
  2. 该方法将返回包含指定元素的Stream对象。

例如,以下代码演示了如何使用of()方法创建一个包含单个元素的Stream对象:

Stream stream = Stream.of("Hello");

上述代码将创建一个包含字符串"Hello"的Stream对象。可以根据需要使用该流进行后续操作,例如过滤、映射、排序等操作。

 empty()

empty() 方法是用来创建一个不包含任何元素的空流。

下面是一个使用示例:

import java.util.stream.Stream;

public class StreamEmptyExample {
    public static void main(String[] args) {
        Stream emptyStream = Stream.empty();
        System.out.println("Count: " + emptyStream.count()); // 输出 Count: 0
    }
}

以上代码展示了如何使用 empty() 方法创建一个空流。直接调用 Stream.empty() 方法即可得到一个不包含任何元素的空流。接着,使用 count() 方法获取流中元素的数量,由于该流为空,所以返回值为 0。最终将其打印出来。

需要注意的是,由于该流不包含任何元素,因此对它进行任何操作都不会有任何影响,也不会引发任何异常。

generate(Supplier s)

generate() 方法是 Stream 类中的一个静态方法,它接收一个 Supplier 函数作为参数,用于生成元素序列。generate() 方法会按照生成函数的逻辑无限地生成元素,直到达到流的上限或被用户中断。

例如,假设需要生成一个由随机整数构成的流,可以使用 generate() 方法实现:

Random random = new Random();
Stream intStream = Stream.generate(() -> random.nextInt(100));

以上代码中,首先创建了一个 Random 对象用于生成随机整数,然后通过 Stream.generate() 方法创建了一个新的流,并传入一个生成函数 () -> random.nextInt(100),用于生成随机整数。由于 generate() 方法不会限制元素数量,因此这个流会一直生成随机整数,直到被强制停止。

需要注意的是,由于 generate() 方法生成的流是无限的,因此如果不对流进行限制,可能会导致程序陷入死循环或内存溢出等问题。如果需要将流转换为有限长度的流,可以使用 limit() 方法或 takeWhile() 方法。

另外,由于 generate() 方法是一个静态方法,因此可以在任何地方调用它创建新的流。同时,由于生成函数是无状态的,因此可以并行生成元素以提高效率。

iterate(T seed, UnaryOperator f)

iterate() 方法是 Stream 类中的一个静态方法,它接收一个起始元素和一个一元操作函数作为参数,用于生成一个包含无限连续元素的流。iterate() 方法会将起始元素作为序列的第一个元素,并以这个元素为基础,通过一元操作函数不断生成新的元素。

例如,假设需要生成一个包含斐波那契数列的流,可以使用 iterate() 方法实现:

Stream.iterate(new int[]{0, 1}, arr -> new int[]{arr[1], arr[0] + arr[1]})
      .mapToInt(arr -> arr[0])
      .limit(10)
      .forEach(System.out::println);

以上代码中,首先通过 Stream.iterate() 方法定义了一个起始元素 {0, 1} 和一元操作函数 arr -> new int[]{arr[1], arr[0] + arr[1]},用于生成下一个斐波那契数列元素。然后通过 mapToInt() 方法将每个元素转换为斐波那契数列中的第一个数,并通过 limit() 方法限制了元素数量为 10。最后通过 forEach() 方法将每个元素输出到控制台。

需要注意的是,由于 iterate() 方法生成的流是无限的,因此如果不对流进行限制,可能会导致程序陷入死循环或内存溢出等问题。如果需要将流转换为有限长度的流,可以使用 limit() 方法或 takeWhile() 方法。

另外,由于一元操作函数是无状态的,因此可以并行生成元素以提高效率。同时,由于 iterate() 方法生成的流是有序的,因此不建议在并行流中使用。

 concat(Stream a, Stream b)

Stream 接口中的静态方法 concat(Stream a, Stream b) 可以将两个流连接起来,形成一个新的流。这个新的流包含了两个原始流的所有元素,先按照第一个流的顺序排列,然后再按照第二个流的顺序排列。

下面是一个使用示例:

import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;
import java.util.stream.Stream;

public class StreamConcatExample {
    public static void main(String[] args) {
        List list1 = Arrays.asList("A", "B", "C");
        List list2 = Arrays.asList("D", "E", "F");

        Stream stream1 = list1.stream();
        Stream stream2 = list2.stream();

        Stream concatStream = Stream.concat(stream1, stream2);

        List result = concatStream.collect(Collectors.toList());

        System.out.println(result); // [A, B, C, D, E, F]
    }
}

以上代码展示了如何使用 concat() 方法连接两个字符串列表的示例。首先创建了两个列表 list1list2,然后通过 stream() 方法将它们转换为流,得到两个流 stream1stream2。接着,通过 concat(stream1, stream2) 方法将这两个流连接起来,得到一个新的流 concatStream,该流包含了两个原始流中的所有元素。最后,通过 collect(Collectors.toList()) 方法将该新流中的元素收集到一个列表中,得到一个包含所有元素的列表 result

需要注意的是,在使用 concat() 方法时,需要保证两个流中的元素类型相同。另外,一旦某个流被操作过,比如使用了 filtermap 等方法,那么就不能再对该流进行连接操作,否则会抛出 IllegalStateException 异常。

 builder()

用于创建可变的、支持添加元素的 Stream

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

Stream stream = Stream.builder()
        .add("apple")
        .add("banana")
        .add("orange")
        .build();

stream.forEach(System.out::println);

上述代码中,首先使用 Stream.builder() 创建了一个 Stream.Builder 对象,然后使用 add() 方法向该对象中添加了三个字符串元素。最后通过调用 build() 方法创建了一个新的 Stream 对象,并使用 forEach() 方法输出其中的元素。

需要注意的是,由于 Stream.Builder 是可变的,所以应当仅在必要的情况下使用 builder() 方法来创建 Stream 对象。在其他情况下,应当使用不可变的集合或数组来创建 Stream 对象,以避免出现并发问题。

 ofNullable(T t)

Java 8 中的 Stream 类提供了 ofNullable(T t) 方法,用于创建包含零个或一个元素的流对象。该方法接受一个类型为 T 的参数 t,可以是任何对象,包括 null。如果参数 t 不为 null,那么将创建一个包含该元素的、长度为1的流;否则,将创建一个空流,即不包含任何元素。

该方法返回的是一个 Optional 对象,可以通过调用其 stream() 方法来获取对应的 Stream 流对象。如果参数 t 不为 null,则该流对象中仅包含一个元素 t;否则,该流对象为空。

举例来说,我们可以使用 ofNullable(T t) 方法来判断一个对象是否为 null,并将其转换为一个流对象。例如:

String str = null;
Stream stream = Stream.ofNullable(str);
 
   

上述代码将创建一个空流对象 stream,因为 str 为 null。如果 str 非空,则会创建包含 str 元素的流对象。

ofNullable(T t) 方法通常用于处理类似数据源为空时的情况,例如在流式计算中,当数据源为空时需要特殊处理,此时可以使用 ofNullable() 方法来方便地将其转换为空流对象。同时,该方法还可以用于简化一些流式计算的操作,例如使用 filter() 方法过滤空值时,可以借助 ofNullable() 方法将空值转换为空流对象后再进行过滤。

总之,ofNullable(T t) 方法可以方便地将一个对象转换为包含零个或一个元素的流对象,通常用于处理空值情况和简化编码操作。

range(int startInclusive, int endExclusive)

range(int startInclusive, int endExclusive) 是 Java 8 中 Stream 类提供的一个静态方法,用于创建一个包含从 startInclusive 开始(含)到 endExclusive 结束(不含)的整数序列流对象。该方法返回的是一个 IntStream 流对象,可以对该流进行各种操作。

下面是一个示例,演示如何使用 range() 方法创建一个整数序列流:

IntStream intStream = IntStream.range(1, 10);
intStream.forEach(System.out::print); // 输出:123456789

上述代码中,我们使用 range() 方法创建了一个从1到10的整数序列流对象,并将其存储在 intStream 变量中。然后,我们调用 intStream 对象的 forEach() 方法,使用方法引用 System.out::print 来依次输出每个元素,从而得到了1到9的输出结果。

需要注意的是,使用 range() 方法创建的整数序列流对象不包含结束值 endExclusive,即该区间是左闭右开的。因此,在上述示例中,输出的结果是从1到9,不包括数字 10。

rangeClosed(int startInclusive, int endInclusive) 

rangeClosed(int startInclusive, int endInclusive) 是 Java 8 中 Stream 类提供的一个静态方法,用于创建一个包含从 startInclusive 开始(含)到 endInclusive 结束(含)的整数序列流对象。该方法返回的是一个 IntStream 流对象,可以对该流进行各种操作。

下面是一个示例,演示如何使用 rangeClosed() 方法创建一个整数序列流:

IntStream intStream = IntStream.rangeClosed(1, 10);
intStream.forEach(System.out::print); // 输出:12345678910

上述代码中,我们使用 rangeClosed() 方法创建了一个从1到10的整数序列流对象,并将其存储在 intStream 变量中。然后,我们调用 intStream 对象的 forEach() 方法,使用方法引用 System.out::print 来依次输出每个元素,从而得到了1到10的输出结果。

需要注意的是,使用 rangeClosed() 方法创建的整数序列流对象包含结束值 endInclusive,即该区间是左闭右闭的。因此,在上述示例中,输出的结果是从1到10,包括数字 10。

你可能感兴趣的:(java,java,开发语言)