I have a row which I need to parse which looks like:
@UNIT,a,b,c,,,,d,e,,,
and I expect Java to store the following values in a list:
[0] => a
[1] => b
[2] => c
[3] => null
[4] => null
[5] => null
[6] => d
[7] => e
[8] => null
[9] => null
[10] => null
I want to comma separate the values by comma and replace empty values with null
.
I archive most of the part with the following code:
metaObject.unit = Arrays.stream(line
.split(","))
.skip(line.startsWith("@UNIT,") ? 1 : 0)
.map(String::trim)
.map(s -> " ".equals(s) || "".equals(s) || "_".equals(s)? null : s)
.collect(Collectors.toList());
Where metaObject.unit
is defined as List<String> unit = new ArrayList<String>();
The problem is that Java ignores the empty elements which occure after the last non-empty element. The output I get in the given case is:
[0] => a
[1] => b
[2] => c
[3] => null
[4] => null
[5] => null
[6] => d
[7] => e
I do not understand why Java does not threat the empty elements as before. Is there any trick to get this fixed?
A lambda expression cannot throw any checked exception until its corresponding functional interface declares a throws clause. An exception thrown by any lambda expression can be of the same type or sub-type of the exception declared in the throws clause of its functional interface.
Because IOException is a checked exception, we must handle it explicitly. We have two options. First, we may simply throw the exception outside of our method and take care of it somewhere else. Alternatively, we can handle it inside the method that uses a lambda expression.
In Java 8, it is also possible for the body of a lambda expression to be a complex expression or statement, which means a lambda expression consisting of more than one line. In that case, the semicolons are necessary. If the lambda expression returns a result then the return keyword is also required.
The problem actually comes from line.split(",")
.
By default, quoting the Javadoc of split(regex)
:
Trailing empty strings are therefore not included in the resulting array.
So the result of this call is [@UNIT, a, b, c, , , , d, e]
.
What you want is to include the trailing empty strings, so you need to call line.split(",", -1)
(note the negative second parameter). Quoting the Javadoc of split(regex, limit)
, about the limit
parameter:
If n is non-positive then the pattern will be applied as many times as possible and the array can have any length.
Corrected code:
metaObject.unit = Arrays.stream(line
.split(",", -1))
.skip(line.startsWith("@UNIT,") ? 1 : 0)
.map(String::trim)
.map(s -> s.isEmpty() || "_".equals(s) ? null : s)
.collect(Collectors.toList());
(Note that I removed the call to " ".equals(s)
since if that were the case, the preceding call to trim
would have made that String an empty String, and, as Holger points out in his comment, I replaced "".equals(s)
with the cleaner s.isEmpty()
).
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