如何在Java 8中从流创建一个二维数组?
如何在Java 8中从流创建一个二维数组?
我有一个像这样的文本文件:
ids.txt
1000 999 745 123 ...
我想读取这个文件并将其加载到一个二维数组中。我期望得到一个类似下面的数组:
Object[][] data = new Object[][] { // { new Integer(1000) }, // { new Integer(999) }, // { new Integer(745) }, // { new Integer(123) }, // ... };
这是我写的代码:
File idsFile = ... ; try (StreamidsStream = Files.lines(idsFile.toPath(), StandardCharsets.US_ASCII)) { Object[][] ids = idsStream .filter(s -> s.trim().length() > 0) .toArray(size -> new Object[size][]); // 在这里处理ids数组... }
运行这段代码时,会引发异常:
java.lang.ArrayStoreException: null at java.lang.System.arraycopy(Native Method) ~[na:1.8.0_45] at java.util.stream.SpinedBuffer.copyInto(Unknown Source) ~[na:1.8.0_45] at java.util.stream.Nodes$SpinedNodeBuilder.copyInto(Unknown Source) ~[na:1.8.0_45] at java.util.stream.SpinedBuffer.asArray(Unknown Source) ~[na:1.8.0_45] at java.util.stream.Nodes$SpinedNodeBuilder.asArray(Unknown Source) ~[na:1.8.0_45] at java.util.stream.ReferencePipeline.toArray(Unknown Source) ~[na:1.8.0_45] ...
如何解决这个异常呢?
在Java 8中,如果给定一个`Stream
strings .filter(s -> s.trim().length() > 0) .map(Integer::parseInt) .map(i -> new Object[]{i})
现在,要将这个结果转换为一个`Object[][]`,你可以简单地这样做:
Object[][] result = strings .filter(s -> s.trim().length() > 0) .map(Integer::parseInt) .map(i -> new Object[]{i}) .toArray(Object[][]::new);
对于输入:
final Streamstrings = Stream.of("1000", "999", "745", "123");
输出将是:
[[1000], [999], [745], [123]]
如果你怀疑字符串可能会偶尔在前后有空格,那么最好添加一个单独的`trim`步骤:`strings.map(String::trim).filter(s -> !s.isEmpty())`。此外,我建议使用`Integer::valueOf`而不是`Integer::parseInt`,因为它更符合所需的类型(`Integer`而不是`int`)。虽然这可能只是个人偏好的问题。
为什么"最好添加一个单独的trim步骤"呢?
这样你就可以解析带有数字后面的空格的文件(例如`"1 \n2\n3 \n"`)。目前,对于这样的文件,你将会得到`NumberFormatException`。
你认为这两个`map`操作比简单地使用`.map(s -> new Object[]{Integer.parseInt(s)})`有什么好处吗?
我不太清楚。我喜欢将每个逻辑转换拆分为单独的`map`步骤 - 我认为这样使代码更易读。我认为这只是个人喜好的问题 - 我怀疑这不会对性能产生太大影响。
问题:如何在Java 8中从流中创建一个二维数组?
原因:在Java 8中,我们可能遇到需要从流中创建一个二维数组的情况。我们可能有一个包含一系列数字的文件,我们想要将这些数字存储在一个二维数组中以便进一步处理。
解决方法:
我们可以使用Java 8中的流操作来解决这个问题。下面是一个示例代码片段,展示了如何从流中创建一个二维数组:
try (StreamidsStream = Files.lines(idsFile.toPath(), StandardCharsets.US_ASCII)) { Object[][] ids = idsStream .map(String::trim) .filter(s -> !s.isEmpty()) .map(Integer::valueOf) .map(i -> new Integer[] { i }) .toArray(Object[][]::new); // 在这里处理ids数组... }
在上面的代码中,我们首先使用`Files.lines()`方法从文件中获取一个字符串流。然后,我们对流进行一系列的操作来处理和转换字符串。首先,我们使用`map()`方法来去除每个字符串的前后空格。接下来,我们使用`filter()`方法过滤掉空字符串。然后,我们使用`map()`方法将字符串转换为整数。最后,我们使用`map()`方法将整数转换为一个包含这个整数的单元素整数数组。最后,我们使用`toArray()`方法将所有这些单元素整数数组收集到一个二维数组中。在处理完二维数组后,我们可以在注释的位置继续处理它。
通过以上的解决方法,我们可以在Java 8中从流中创建一个二维数组。