本章介绍Stream 创建流的操作:创建流指的是将一个集合或其他数据源转换为 Stream 流对象的过程。通常情况下,我们可以使用 Stream 类的静态方法来创建流对象,如 Stream.of()、Collections.stream() 等。这些方法将返回一个 Stream 流对象,该对象可用于对数据进行各种操作。下面是一些常用的创建流的方法。Java8 Stream详解及中间操作创建方法使用示例(一)
- of(T... values):创建一个由指定元素组成的流。
- empty():创建一个空的流。
- generate(Supplier
s):创建一个无限流,每次调用 get() 方法都会生成新的数据。 - iterate(T seed, UnaryOperator
f):创建一个无限流,在每次迭代时都会应用指定的函数。 - concat(Stream extends T> a, Stream extends T> b):创建一个包含两个流的顺序流,先是流 a,再是流 b。
- builder():创建一个用于构建链式操作的 Builder 对象。
- ofNullable(T t):创建一个包含零个或一个元素的流,元素为指定对象(可以为 null)。
- range(int startInclusive, int endExclusive):创建一个包含从 startInclusive 开始(含)到 endExclusive 结束(不含)的整数序列流。
- rangeClosed(int startInclusive, int endInclusive):创建一个包含从 startInclusive 开始(含)到 endInclusive 结束(含)的整数序列流。
Stream的of(T... values)方法是一个静态方法,用于创建一个包含指定元素的顺序Stream对象。
具体用法如下:
- 调用of(T... values)方法并传入一个或多个元素。
- 该方法将返回包含指定元素的Stream对象。
例如,以下代码演示了如何使用of()方法创建一个包含多个元素的Stream对象:
Stream
stream = Stream.of(1, 2, 3, 4, 5); 上述代码将创建一个包含整数1到5的Stream对象。可以根据需要使用该流进行后续操作,例如过滤、映射、排序等操作。
Stream的of(T t)方法是一个静态方法,用于创建一个包含单个元素的顺序Stream对象。
具体用法如下:
- 调用of(T t)方法并传入一个元素。
- 该方法将返回包含指定元素的Stream对象。
例如,以下代码演示了如何使用of()方法创建一个包含单个元素的Stream对象:
Stream
stream = Stream.of("Hello"); 上述代码将创建一个包含字符串"Hello"的Stream对象。可以根据需要使用该流进行后续操作,例如过滤、映射、排序等操作。
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()
方法是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()
方法是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()
方法生成的流是有序的,因此不建议在并行流中使用。
Stream
接口中的静态方法concat(Stream extends T> a, Stream extends T> 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()
方法连接两个字符串列表的示例。首先创建了两个列表list1
和list2
,然后通过stream()
方法将它们转换为流,得到两个流stream1
和stream2
。接着,通过concat(stream1, stream2)
方法将这两个流连接起来,得到一个新的流concatStream
,该流包含了两个原始流中的所有元素。最后,通过collect(Collectors.toList())
方法将该新流中的元素收集到一个列表中,得到一个包含所有元素的列表result
。需要注意的是,在使用
concat()
方法时,需要保证两个流中的元素类型相同。另外,一旦某个流被操作过,比如使用了filter
、map
等方法,那么就不能再对该流进行连接操作,否则会抛出IllegalStateException
异常。
用于创建可变的、支持添加元素的
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
对象,以避免出现并发问题。
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) 是 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) 是 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。