Java中的Lambda函数跳过元素

Dru*_*dge 7 java lambda java-8 java-stream

我有一行我需要解析看起来像:

@UNIT,a,b,c,,,,d,e,,,

我希望Java在列表中存储以下值:

[0] => a
[1] => b
[2] => c
[3] => null
[4] => null
[5] => null
[6] => d
[7] => e
[8] => null
[9] => null
[10] => null
Run Code Online (Sandbox Code Playgroud)

我想用逗号分隔值,并用空格替换空值null.

我使用以下代码存档大部分内容:

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());
Run Code Online (Sandbox Code Playgroud)

在哪里metaObject.unit定义为List<String> unit = new ArrayList<String>();

问题是Java忽略了在最后一个非空元素之后出现的空元素.我在给定的情况下得到的输出是:

[0] => a
[1] => b
[2] => c
[3] => null
[4] => null
[5] => null
[6] => d
[7] => e
Run Code Online (Sandbox Code Playgroud)

我不明白为什么Java不像以前那样威胁空元素.有没有办法解决这个问题?

Tun*_*aki 8

问题实际上来自于line.split(",").

默认情况下,引用Javadoc split(regex):

因此,结尾的空字符串不包含在结果数组中.

所以这个电话的结果是[@UNIT, a, b, c, , , , d, e].

你想要的是包括尾随的空字符串,所以你需要调用line.split(",", -1)(注意负的第二个参数).引用split(regex, limit)关于limit参数的Javadoc :

如果n是非正数,那么模式将被应用尽可能多的次数,并且数组可以具有任何长度.

更正代码:

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());
Run Code Online (Sandbox Code Playgroud)

(注意我删除了调用," ".equals(s)因为如果是这种情况,前面的调用trim会使String成为一个空字符串,并且,正如Holger在他的评论中指出的那样,我"".equals(s)用清洁器代替s.isEmpty()).

  • 然后你可以用`s.isEmpty()`替换``".equals(s)`,它更干净,imho. (3认同)