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.
Normally I would use a String.split('\n')
for accumulating the rows into an array of String
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.
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.
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.
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.
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.
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:
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));
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) :
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());
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With