字符串数组上的 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

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-11-02 22:37:12  来源:igfitidea点击:

Java 8 streams on string arrays

javaarrayscollectionsjava-8java-stream

提问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 Patternwith the line separator and split the input Stringas 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并将输入拆分StringStream. 然后,每行用一个空格分割(只保留 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 splitAsStreamcan be advantageous over Stream.of(...)if the input Stringis long.

如果输入很长,使用splitAsStream可能会更有优势。Stream.of(...)String

I assumed in the code that the line separator of the Stringwas the default line separator (System.lineSeparator()) of the OS but you can change that if it is not.

我在代码中假设 的行分隔符StringSystem.lineSeparator()操作系统的默认行分隔符 ( ),但如果不是,您可以更改它。



Instead, if you are reading from a file, you could use Files.lines()to get a hold of a Streamof 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 Streamof Strings that represent a single MyObjectinstance, and transform each of them to your MyObjectinstance (by first splitting them again and then constructing a MyObjectinstance) :

您可以生成代表单个实例的a Streamof Strings 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());