我有一个格式的字符串:
row1col1 row1col2
row2col1 row2col2
row3col1 row3col2
等等……
我想提取每个项目并构建一个具有如下属性的对象数组:
new MyObject(row1col1, row1col2);
我是 Java 8 和 Streams 的新手,我想知道如何在没有循环的情况下实现这一目标。
通常我会使用 String.split('\n')
将行累积到一个字符串数组中
然后循环,对于每一行,我将在空格分隔符上再次拆分,并使用两个元素的结果数组 (row1col1 row1col2
) 构建我的对象,直到没有更多的行可以过程。
像这样:
String sausage = "row1col1 row1col2\nrow2col1 row2col2\nrow3col1 row3col2";
String[] rows = sausage.split("\n");
for (String row : rows) {
String[] objectData = u.split("\\s+");
MyObject myObject = new MyObject(objectData[0], objectData[1]);
myObjectList.add(myObject);
}
任何人都可以向我解释如何使用流实现相同的目的,以及允许我这样做的背后机制是什么?
当增加元素数量时,这是否是一种有效的思考方式,因为从所有示例中我看到流专注于过滤、收集或通常给定一组元素检索应用某些标准的次要集合。
最佳答案
一个简单的方法是创建一个带有行分隔符的 Pattern
并将输入 String
拆分为 Stream
。然后,每行用一个空格分隔(只保留 2 个部分)并映射到一个 MyObject
。最后,用结果构造一个数组。
public static void main(String[] args) {
String str = "row1col1 row2col2\r\nrow2col1 row2col2\r\nrow3col1 row3col2";
MyObject[] array =
Pattern.compile(System.lineSeparator(), Pattern.LITERAL)
.splitAsStream(str)
.map(s -> s.split("\\s+", 2))
.map(a -> new MyObject(a[0], a[1]))
.toArray(MyObject[]::new);
System.out.println(Arrays.toString(array));
}
使用 splitAsStream
如果输入 String
很长,则优于 Stream.of(...)
。
我在代码中假定 String
的行分隔符是操作系统的默认行分隔符 (System.lineSeparator()
),但您可以更改它,如果它不是。
相反,如果您正在从文件中读取数据,则可以使用 Files.lines()
获取文件中所有行的 Stream
:
MyObject[] array = Files.lines(path)
.map(s -> s.split("\\s+", 2))
.map(a -> new MyObject(a[0], a[1]))
.toArray(MyObject[]::new);
System.out.println(Arrays.toString(array));
关于字符串数组上的 Java 8 流,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34219090/