我有一个格式的字符串:
row1col1 row1col2
row2col1 row2col2
row3col1 row3col2
依旧......
我想提取每个项目并构建一个具有以下属性的对象数组:
new MyObject(row1col1, row1col2);
我是Java 8和Streams的新手,我想知道如何在没有循环的情况下实现这一点。
通常我会使用String.split('\n')
将行累积到String
然后是一个循环,我将在空格分隔符上再次拆分每一行,并使用两个元素的结果数组(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);
}
任何人都可以向我解释如何使用流来实现相同的目标,这背后的机制是什么让我这样做?
当增加元素数量时,这甚至是一种有效的思维方式,因为从所有的例子中我看到流集中在过滤,收集或通常给出一组元素检索应用一些标准的次要集。
答案 0 :(得分:11)
一种简单的方法是使用行分隔符创建String
,并将输入Stream
拆分为MyObject
。然后,每行用空格分割(仅保留2个部分)并映射到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));
}
。最后,使用结果构造一个数组。
Stream.of(...)
如果输入String
很长,则使用splitAsStream
优于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));
:
public static class MyClass {
static MyClass() {
DoStuff("HardCodedParameter")
}
}
答案 1 :(得分:5)
您可以生成代表单个Stream
实例的String
个MyObject
,并将每个实例转换为MyObject
个实例(首先将它们再次拆分为然后构建一个MyObject
实例):
List<MyObject> list =
Stream.of(inputString.split("\n"))
.map (s -> s.split(" "))
.filter (arr -> arr.length == 2) // this validation may not be necessary
// if you are sure each line contains 2 tokens
.map (arr -> new MyObject(arr[0],arr[1]))
.collect(Collectors.toList());