Java字符串拆分删除空值

Posted

技术标签:

【中文标题】Java字符串拆分删除空值【英文标题】:Java String split removed empty values 【发布时间】:2013-01-14 03:42:04 【问题描述】:

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

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 值在任何地方出现,它都应该在数组中。

【问题讨论】:

【参考方案1】:

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

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

更多细节:split(regex) 内部返回split(regex, 0) 的结果,您可以在此方法的documentation 中找到(强调我的)

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

如果n 的限制大于零,那么该模式将最多应用 n - 1 次,数组的长度将不大于 n,并且数组的最后一个条目将包含超出最后一个匹配分隔符的所有输入。

如果n非正数,则该模式将被应用尽可能多的次数,并且数组可以有任意长度。

如果n,则该模式将被应用尽可能多的次数,数组可以有任意长度,尾随的空字符串将被丢弃

例外

值得一提的是,删除尾随的空字符串才有意义只有当这样的空字符串是由拆分机制创建时。所以对于"".split(anything),因为我们不能进一步拆分"",我们将得到[""]数组的结果。 发生这种情况是因为这里没有发生拆分,所以 "" 尽管为空且尾随代表 original 字符串,而不是通过拆分过程创建的空字符串。

【讨论】:

哇。效果很好。但是 -1 这如何改变一切? 你甚至可以试试data.split("\\|", 8) 不要使用split("\\|", 8),因为这限制了前八个标记!如果你的字符串是可变的,你应该使用split("\\|", -1),这样它就可以创建一个无限的数字的标记,并且不会在最后丢弃空标记。 @Reddy -1(其实也可以是任何负数,绝对值是多少都无所谓)告诉split方法把空token保留在最后.默认值为 0,它告诉方法丢弃数组末尾的空标记。 显然,很多人认为保留尾随空字符串是split(regex) 的默认功能。他们到了这里,发现事实并非如此。【参考方案2】:

你可能有多个分隔符,包括空格字符、逗号、分号等。用 []+ 将可重复组中的那些带入,例如:

 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]+");

添加空格以防万一您将它们与 | 一起用作分隔符

【讨论】:

【参考方案3】:

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 中添加 ",$"。

【讨论】:

【参考方案4】:

来自String.split(String regex)的文档:

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

所以你将不得不使用带有负值的两个参数版本String.split(String regex, int limit)

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

文档:

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

这不会遗漏任何空元素,包括尾随元素。

【讨论】:

【参考方案5】:

来自String.split() API Doc

围绕给定正则表达式的匹配拆分此字符串。 此方法的工作方式就像通过调用双参数拆分方法一样 给定的表达式和零的极限参数。尾随空 因此字符串不包含在结果数组中。

重载的String.split(regex, int) 更适合你的情况。

【讨论】:

这解释了行为但没有回答问题。 @assylias 现在将其添加到我的答案中 :)

以上是关于Java字符串拆分删除空值的主要内容,如果未能解决你的问题,请参考以下文章

如何在不将空值发送到输出数组的情况下拆分字符串

java - 如何在java中将字符串元素拆分为不相交的组?

java 怎样将数组里的元素进行拆分

Java:使用正则表达式拆分字符串而不删除分隔符[重复]

C# 正则表达式拆分为 Java 模式拆分

java里一段字符串按照空格拆分,然后再按逗号拆分怎么写