翻译 | Java 中 Stream 与 Array 间的相互转换

2019-05-191912

翻译 | Java 中 Stream 与 Array 间的相互转换

原文自工程师baeldung博客,作者为 baeldung,传送门

1. 综述

将各种各样的动态数据类型转换为数组在 java 中是非常普遍的。

在这篇文章中,将说明如何处理 stream 和 array 间的相互转换。

2. 将 stream 转换为 array

2.1. 方法引用

将 stream 转换为 array 的最好方法是使用 stream 的 toArray() 方法

public String[] usingMethodReference(Stream<String> stringStream) {
    return stringStream.toArray(String[]::new);
}

现在,我们可以简单测试下转换是否能够顺利执行:

Stream<String> stringStream = Stream.of("baeldung", "convert", "to", "string", "array");
assertArrayEquals(new String[] { "baeldung", "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. 自定义类

或者,我们能够用自己的方式,创建一个完整的类来处理。

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 stream 转换为 String array。事实上,我们可以使用上述转换方法去处理任何 Object 并且和上述的 String 例子非常相像。

但对基本数据类型有点不一样。例如,如果我们需要将 Integer stream 转换为 int[],首先我们需要调用 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. 将 array 转换为 stream

理所当然,我们也可以去处理相反的情况。并且 java 也提供了一些专门的方法来处理。

3.1. objects 数组

我们能够转换 array 到 stream ,通过使用 Arrays.stream() 或者 Stream.of() 方法:

public Stream<String> stringArrayToStreamUsingArraysStream(String[] stringArray) {
    return Arrays.stream(stringArray);
}

public Stream<String> stringArrayToStreamUsingStreamOf(String[] stringArray) {
    return Stream.of(stringArray);
}

我们应该注意到,在这两种情况下,我们的 stream 和 array 是同时出现的。

3.2. 基础数据类型数组

相同地,我们可以对基础数据类型数组进行转换:

public IntStream primitiveIntArrayToStreamUsingArraysStream(int[] intArray) {
    return Arrays.stream(intArray);
}

public Stream<int[]> primitiveIntArrayToStreamUsingStreamOf(int[] intArray) {
    return Stream.of(intArray);
}

但是,与转换 Objects 数组相比,这里存在重要的差异。当转换基础数据类型数组的时候,Arrays.stream() 返回 IntStream, 但是 Stream.of() 则返回 Stream<int[]>

3.3. Arrays.stream vs. 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() 实际上是在内部调用 * c*,很明显,这就是我们能够得到相同结果的原因。

现在,当我们需要转换一个基本类型数组时,我们来检查下这种情况下的方法:

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() 方法再也没调用 Stream.of() 方法了。

4. 结论

在这篇文章中,我们看到在 java 中 stream 和 array 是怎么做相互转换的。我们也解释了为什么在转换 Objects 数组和基本数据类型数组时得到了不同的结果。

和往常一样,在 GitHub 上可以找到我们的例子代码。

分享
点赞1
打赏
上一篇:Docker常用命令笔记(一)
下一篇:ELK日志统一管理系统的搭建