字符串数组上的 Java 8 流
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/34219090/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Java 8 streams on string arrays
提问by Lucian Enache
I have a single String of format:
我有一个格式字符串:
row1col1 row1col2
row2col1 row2col2
row3col1 row3col2
and so on...
等等...
I want to extract each item and build an array of objects with properties like this:
我想提取每个项目并构建一个具有如下属性的对象数组:
new MyObject(row1col1, row1col2);
I am new to Java 8 and Streams and I would like to find out how can I achieve this without loops.
我是 Java 8 和 Streams 的新手,我想知道如何在没有循环的情况下实现这一点。
Normally I would use a String.split('\n')
for accumulating the rows into an array of String
通常我会使用 aString.split('\n')
将行累积到一个字符串数组中
And then a loop where for each line I would split again on the space separator and with the resulting array of the two elements (row1col1 row1col2
) build my object, until there are no more rows to process.
然后是一个循环,对于每一行,我将在空格分隔符上再次拆分,并使用两个元素 ( row1col1 row1col2
)的结果数组构建我的对象,直到没有更多行要处理。
Like this:
像这样:
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);
}
Can anyone explain me how to achieve the same with streams and what is the mechanism behind that allows me to do so?
任何人都可以解释我如何使用流实现相同的目标,以及允许我这样做的背后机制是什么?
Is this even a valid way of thinking when increasing the number of elements because from all the examples I've seen the streams focus on filtering, collecting or generally given a set of elements retrieve a minor set applying some criterias.
在增加元素数量时,这是否甚至是一种有效的思维方式,因为从我看到的所有示例中,流都专注于过滤、收集或通常给定一组元素并应用某些标准检索次要集合。
采纳答案by Tunaki
A simple way would be to create a Pattern
with the line separator and split the input String
as a Stream
. Then, each line is split with a space (keeping only 2 parts) and mapped to a MyObject
. Finally, an array is constructed with the result.
一种简单的方法是Pattern
使用行分隔符创建 a并将输入拆分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));
}
Using splitAsStream
can be advantageous over Stream.of(...)
if the input String
is long.
如果输入很长,使用splitAsStream
可能会更有优势。Stream.of(...)
String
I assumed in the code that the line separator of the String
was the default line separator (System.lineSeparator()
) of the OS but you can change that if it is not.
我在代码中假设 的行分隔符String
是System.lineSeparator()
操作系统的默认行分隔符 ( ),但如果不是,您可以更改它。
Instead, if you are reading from a file, you could use Files.lines()
to get a hold of a Stream
of all the lines in the file:
相反,如果您正在从文件中读取数据,则可以使用Files.lines()
来获取Stream
文件中所有行的 a :
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));
回答by Eran
You could generate a Stream
of String
s that represent a single MyObject
instance, and transform each of them to your MyObject
instance (by first splitting them again and then constructing a MyObject
instance) :
您可以生成代表单个实例的a Stream
of String
s 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());