我有一个格式的字符串:
row1col1 row1col2 row2col1 row2col2 row3col1 row3col2
等等...
我想提取每个项目并构建一个具有以下属性的对象数组:
new MyObject(row1col1, row1col2);
我是Java 8和Streams的新手,我想知道如何在没有循环的情况下实现这一点.
通常我会使用a 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); }
谁能解释我如何用流来实现同样的目标,那背后的机制是什么让我这样做呢?
在增加元素数量时,这甚至是一种有效的思维方式,因为从我看到的所有示例中,流程都集中在过滤,收集或通常给出一组元素检索应用一些标准的次要集合.
一种简单的方法是Pattern
使用行分隔符创建一个并将输入拆分String
为Stream
.然后,每一行用空格分割(仅保留2个部分)并映射到a 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
,Stream.of(...)
则使用可能是有利的String
.
我在代码中假设该行的分隔符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));
您可以生成一个代表单个实例Stream
的String
s MyObject
,并将它们转换为您的MyObject
实例(首先将它们再次拆分然后再构建一个MyObject
实例):
Listlist = 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());