Java字符串分割函数表现奇怪

5

我在使用Java中的split()方法时发现了奇怪的行为。

我有一个字符串,如下所示:0|1|2|3|4|5|6|7|8|9|10

String currentString[] = br.readLine().split("\\|");
System.out.println("Length:"+currentString.length);
for(int i=0;i < currentString.length;i++){
     System.out.println(currentString[i]);
}

这将产生所需的结果:
Length: 11
0
1
2
3
4
5
6
7
8
9
10

然而,如果我收到字符串:0|1|2|3|4|5|6|7|8||

我会得到以下结果:

Length: 8
0
1
2
3
4
5
6
7
8

最后的两个空值被省略了。我需要保留这些空值。不确定我做错了什么。我也尝试过以下方式使用split。...split("\\|",-1);但是那样会返回长度为1的整个字符串。非常感谢任何帮助!

2
一些与您问题无关的小贴士。 我强烈建议您像Paulo Santos一样缩进您的代码,以使其更易于阅读。 此外,您的“C风格”for()循环可以被替换为for(String str:currentString){System.out.println(str);},这样更容易阅读,而且更难出错(例如,意外使用<=而不是<)。 最后,currentString不是一个字符串,而是一个字符串数组,这有点具有误导性。 考虑将其称为“currentStringArray”或其他类似名称。 - Tyler
我还应该提到,如果我的字符串在第一个和最后一个索引之间的某些分隔符具有空值,则它可以很好地捕获这些空格,只有当最后两个分隔符为空时,它才会表现奇怪。例如: 0 | 1 | 2 | 3 ||| 6 | 7 | 8 | 9 | 10 0 1 2 36 7 8 9 10 - astro
对我来说,它运行得很好,使用-1。请再次检查,确保你没有犯一个简单的错误,比如重新运行代码时忘记重新编译它。 - Tyler
感谢MatrixFrog的建议,我会按照您的建议进行更改。我不确定如何正确地使用标签来格式化我的代码,就像Paulo Santos所做的那样(我已经阅读了相关的常见问题解答,但无法实现反引号方法,只好将其保留)。非常感谢您的帮助和指导。 - astro
6个回答

5
split 方法的默认行为是不返回空令牌(因为有一个零限制)。使用两个参数的split方法,并将限制设置为-1,将在返回中给出所有的空令牌。
更新: 以下是测试代码:
public class Test {
    public static void main(String[] args) {
    String currentString[] = "0|1|2|3|4|5|6|7|8||".split("\\|", -1);
    System.out.println("Length:"+currentString.length); 
    for(int i=0;i < currentString.length;i++){ System.out.println(currentString[i]); }
  }
}

输出如下:
Length:11
0
1
2
3
4
5
6
7
8
--- BLANK LINE --    
--- BLANK LINE --

"

我在这里添加了“--- BLANK LINE ---”以表示返回值为空。它在8|之后的空令牌和最后一个|之后的空尾随令牌中各出现一次。

希望这能澄清事情。

"

我已经尝试使用我帖子中提到的-1,但它返回整个字符串,长度为1。如下所示: 0|1|2|3|4|5|6|7|8||不确定为什么? - astro
实际上,默认情况下只有尾部的空白被删除。 - Kevin Bourrillion

4

String.split()很奇怪。

它的极端怪异性,以及其他方面的怪异性,是我们制作Splitter的原因之一。

它的行为不那么令人惊讶,而且具有很大的灵活性。


1
我不认为在分隔符之间的空字符串被删除是奇怪的。奇怪的是,它只会在末尾删除空字符串,而不是在中间! - Kees Kist

1

我的Java有点生疏,但它不应该是这样的吗:

String currentString[] = "0|1|2|3|4|5|6|7|8||".split("\\|");
System.out.println("Length:"+currentString.length); 
for(int i = 0; i < currentString.length; i++)
{
  System.out.println(currentString[i]); 
} 

请注意双反斜杠。这是因为split()的参数被解释为正则表达式。您想匹配字符“|”,可以使用正则表达式“|”,它由字符串字面量“\|”表示。 - Tyler
我的代码有双斜杠,我不确定为什么在论坛中翻译效果不佳。 - astro
好的,你应该可以编辑你的问题来反映这一点。 - Tyler
@astro - 这是因为你使用了<code>...</code>而不是StackOverflow维基语法。 - Stephen C

0
请检查以下代码,我使用了您的解决方案,它可以正常工作:

public class SplitTest 
{
    public static void main(String[] args)
    {
      String text = "0|1|2|3|4|5|6|7|8||";
      String pattern = "\\|";
      String [] array = text.split(pattern, -1);
          System.out.println("array length:" + array.length);
          for(int i=0; i< array.length; i++) 
          System.out.print(array[i]+ " ");
        } 
 }

输出结果为:
array length:11
0 1 2 3 4 5 6 7 8   

0

你需要使用 indexOf()substring(),才能让它正常工作。我认为你不能仅仅使用 split() 来清空字符串。


1
嗯,不太确定你的意思,请给我一个例子好吗? - astro

0

我认为这是split的默认行为,不过请尝试以下代码:

String currentString[] = br.readLine().replace("||","| |").split("\|"); System.out.println("Length:"+currentString.length); for(int i=0;i < currentString.length;i++){ System.out.println(currentString[i]); }

这段代码还未经过测试,但我认为应该可以解决问题。


这让我更进一步,它将长度增加了一个索引但遗漏了最后一个索引。这是由于最后一个索引以|(值)而不是||结束,因此空格从未添加。我应该使用stringTokenizer方法吗?我知道它已被弃用,但我认为这会更有效,因为我不确定为什么这不按预期运行。 - astro

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