Java字符串分割删除空值

381

我正在尝试使用分隔符拆分值。但是我发现了令人惊讶的结果。

String data = "5|6|7||8|9||";
String[] split = data.split("\\|");
System.out.println(split.length);
我希望能获得8个值。[5,6,7,EMPTY,8,9,EMPTY,EMPTY] 但我只得到了6个值。 有任何建议或修复方法吗?无论EMPTY值出现在哪个位置,都应该在数组中。
5个回答

643

split(delimiter)默认情况下从结果数组中删除尾随的空字符串。要关闭此机制,我们需要使用重载版本的split(delimiter, limit),并将limit设置为负值

String[] split = data.split("\\|", -1);

更多细节如下:
split(regex) 内部返回 split(regex, 0) 的结果,在这个方法的文档中你可以找到以下内容(重点是我自己加的):

limit 参数控制模式被应用的次数,因此影响了结果数组的长度。

如果限制 n大于零 的,那么模式最多会被应用 n - 1 次,数组的长度不会超过 n,数组的最后一个元素将包含所有匹配分隔符后面的输入。

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

如果 n,那么模式将被应用尽可能多的次数,数组可以有任何长度,末尾的空字符串将被丢弃

异常情况:

值得一提的是,仅当这样的空字符串是由分割机制创建时,删除末尾的空字符串才有意义。因此,对于 "".split(anything),由于我们无法进一步分割 "",我们将得到结果为[""] 的数组。
这是因为在这里没有进行拆分,所以 "" 尽管为空且末尾,但代表的是 原始 字符串,而不是由分割过程 创建 的空字符串。


3
哇,那真是太棒了。但是,-1会如何改变一切呢? - RaceBase
1
你甚至可以尝试使用 data.split("\\|", 8) - Subhrajyoti Majumder
26
不要使用split("\\|", 8),因为它会限制只分割前八个标记!如果你的字符串是变量,应该使用split("\\|", -1),这样就可以创建无限数量的标记,并且不会在末尾丢弃空标记。 - ADTC
2
@Reddy -1(或者任何负数,实际上绝对值是多少并不重要)告诉split方法保留末尾的空标记。默认值为0,这告诉该方法在数组末尾丢弃空标记。 - ADTC
16
显然,很多人认为在使用split(regex)时保留尾部空字符串是默认功能。他们来到这里后发现它并不是如此。 - Attila Tanyi
显示剩余3条评论

39

根据String.split(String regex)的文档:

该方法的工作方式就像使用给定表达式和限制参数为零调用二元拆分方法一样。因此,结果数组中不包括尾随空字符串。

因此,您将需要使用带有负值的两个参数版本String.split(String regex, int limit)

String[] split = data.split("\\|",-1);

文档:

如果限制n大于零,则模式最多应用n-1次,数组的长度不会超过n,并且数组的最后一个条目将包含超出最后匹配分隔符的所有输入。 如果n为非正数,则模式将尽可能多地应用,数组可以具有任何长度。 如果n为零,则模式将尽可能多地应用,数组可以具有任何长度,并且尾随空字符串将被丢弃。

这不会省略任何空元素,包括末尾的空元素。


7

String[] split = data.split("\\|",-1);

以上并不是所有情况下的实际要求。上述方法的缺点如下:

Scenerio 1:
When all data are present:
    String data = "5|6|7||8|9|10|";
    String[] split = data.split("\\|");
    String[] splt = data.split("\\|",-1);
    System.out.println(split.length); //output: 7
    System.out.println(splt.length); //output: 8

当数据缺失时:

Scenerio 2: Data Missing
    String data = "5|6|7||8|||";
    String[] split = data.split("\\|");
    String[] splt = data.split("\\|",-1);
    System.out.println(split.length); //output: 5
    System.out.println(splt.length); //output: 8

实际要求长度应为7,尽管有数据缺失。因为存在需要插入数据库或其他情况的情况。我们可以通过以下方法实现。

    String data = "5|6|7||8|||";
    String[] split = data.split("\\|");
    String[] splt = data.replaceAll("\\|$","").split("\\|",-1);
    System.out.println(split.length); //output: 5
    System.out.println(splt.length); //output:7

我在这里做的是,删除字符串结尾的"|",然后将字符串拆分。如果您使用","作为分隔符,则需要在replaceAll中添加",$"。

5
String.split() API文档 中得知:
该方法基于给定的正则表达式将字符串拆分为多个子字符串。此方法的行为就像使用给定表达式和限制参数为0调用两个参数的拆分方法一样。因此,末尾的空字符串不包含在结果数组中。
对于您的情况,更适合使用重载的String.split(regex, int) 方法。

1
这解释了行为,但并没有回答问题。 - assylias
@assylias现在已经将它添加到我的答案中了 :) - PermGenError

3
你可能有多个分隔符,包括空格字符、逗号、分号等。请将它们与[]+一起放在可重复的组中,如下所示:
 String[] tokens = "a , b,  ,c; ;d,      ".split( "[,; \t\n\r]+" );

你将拥有4个令牌——a、b、c、d。

在应用此分割之前,需要删除源字符串中的前导分隔符。

作为问题的答案:

String data = "5|6|7||8|9||";
String[] split = data.split("[\\| \t\n\r]+");

为了防止您使用空格作为分隔符,我们增加了空白字符。|


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接