1. 概述
在本教程中,我们将演示如何在Java中将Stream转换为数组,反之亦然。
2. 将Stream转换为数组
2.1 方法引用
将Stream转换为数组的最佳方法是使用Stream的toArray()方法:
public String[] usingMethodReference(Stream<String> stringStream) {
return stringStream.toArray(String[]::new);
}
现在,我们可以轻松测试转换是否成功:
Stream<String> stringStream = Stream.of("tuyucheng", "convert", "to", "string", "array");
assertArrayEquals(new String[] { "tuyucheng", "convert", "to", "string", "array" },
usingMethodReference(stringStream));
2.2 Lambda表达式
另一个等效方法是将Lambda表达式传递给toArray()方法:
public static String[] usingLambda(Stream<String> stringStream) {
return stringStream.toArray(size -> new String[size]);
}
这将为我们提供与使用方法引用相同的结果。
2.3 自定义类
正如我们从Stream文档中看到的那样,它接收IntFunction作为参数。它将数组大小作为输入并返回该大小的数组。
当然,IntFunction是一个接口,所以我们可以实现它:
class MyArrayFunction implements IntFunction<String[]> {
@Override
public String[] apply(int size) {
return new String[size];
}
};
然后我们可以正常构造和使用:
public String[] usingCustomClass(Stream<String> stringStream) {
return stringStream.toArray(new MyArrayFunction());
}
因此,我们可以做出与之前相同的断言。
2.4 原始类型数组
在前面的部分中,我们探讨了如何将String流转换为String数组。事实上,我们可以对任何对象执行这种转换,它看起来与上面的字符串示例非常相似。
不过,对于原始类型来说有点不同。例如,如果我们有一个要转换为int[]的Integer流,我们首先需要调用mapToInt()方法:
public int[] intStreamToPrimitiveIntArray(Stream<Integer> integerStream) {
return integerStream.mapToInt(i -> i).toArray();
}
我们还可以使用mapToLong()和mapToDouble()方法。另外,请注意这次我们没有向toArray()传递任何参数。
最后,让我们做相等断言并确认正确地得到了int数组:
Stream<Integer> integerStream = IntStream.rangeClosed(1, 7).boxed();
assertArrayEquals(new int[]{1, 2, 3, 4, 5, 6, 7}, intStreamToPrimitiveIntArray(integerStream));
但是,如果我们需要做相反的事情怎么办?让我们来看看。
3. 将数组转换为Stream
当然,我们也可以走另一条路。Java有一些专用的方法。
3.1 对象数组
我们可以使用Arrays.stream()或Stream.of()方法将数组转换为Stream:
public Stream<String> stringArrayToStreamUsingArraysStream(String[] stringArray) {
return Arrays.stream(stringArray);
}
public Stream<String> stringArrayToStreamUsingStreamOf(String[] stringArray) {
return Stream.of(stringArray);
}
我们应该注意,在这两种情况下,我们的Stream与我们的数组同时存在。
3.2 原始类型数组
同样,我们可以转换原始类型数组:
public IntStream primitiveIntArrayToStreamUsingArraysStream(int[] intArray) {
return Arrays.stream(intArray);
}
public Stream<int[]> primitiveIntArrayToStreamUsingStreamOf(int[] intArray) {
return Stream.of(intArray);
}
但是,与转换Object的数组相比,有一个重要的区别。转换原始类型数组时,Arrays.stream()返回IntStream,而Stream.of()返回Stream<int[]>。
3.3 Arrays.stream与Stream.of
为了理解前面几节中提到的差异,我们将看一下相应方法的实现。
我们先来看看Java对这两个方法的实现:
public <T> Stream<T> stream(T[] array) {
return stream(array, 0, array.length);
}
public <T> Stream<T> of(T... values) {
return Arrays.stream(values);
}
我们可以看到Stream.of()实际上是在内部调用Arrays.stream(),这显然是我们得到相同结果的原因。
现在,我们将检查在我们想要转换原始类型数组的情况下的方法:
public IntStream stream(int[] array) {
return stream(array, 0, array.length);
}
public <T> Stream<T> of(T t) {
return StreamSupport.stream(new Streams.StreamBuilderImpl<>(t), false);
}
这一次,Stream.of()没有调用Arrays.stream()。
4. 总结
在本文中,我们了解了如何在Java中将Stream转换为数组,反之亦然。我们还解释了为什么在转换Object数组和使用原始类型数组时会得到不同的结果。
与往常一样,本教程的完整源代码可在GitHub上获得。