Java 与使用带多个分隔符的拆分混淆
我正在练习阅读输入,然后标记它。 例如,如果我有[882337],我只想得到数字882和337。我尝试使用以下代码:Java 与使用带多个分隔符的拆分混淆,java,split,Java,Split,我正在练习阅读输入,然后标记它。 例如,如果我有[882337],我只想得到数字882和337。我尝试使用以下代码: String test = "[882,337]"; String[] tokens = test.split("\\[|\\]|,"); System.out.println(tokens[0]); System.out.println(tokens[1]); System.out.println(tokens[2]); 这是一种工作方
String test = "[882,337]";
String[] tokens = test.split("\\[|\\]|,");
System.out.println(tokens[0]);
System.out.println(tokens[1]);
System.out.println(tokens[2]);
这是一种工作方式,输出为:
(空行)
882
337
我不明白的是为什么令牌[0]是空的?我希望只有两个令牌,其中令牌[0]=882和令牌[1]=337
我查看了一些链接,但没有找到答案
谢谢你的帮助 Split拆分给定的
字符串。如果您在“[”或“,”或“]”上拆分了“[882337]”,那么您实际上有:
- 没什么
- 882
- 337
- 没什么
但是,正如您所调用的String.split(delimiter)
,这将调用String.split(delimiter,limit)
,并且限制为零
从:
limit
参数控制应用阵列的次数,从而影响结果阵列的长度。如果限制n
大于零,则模式将最多应用n-1次,数组长度将不大于n
,数组的最后一个条目将包含最后一个匹配分隔符之外的所有输入。如果n
为非正,则图案将被应用尽可能多的次数,并且阵列可以有任何长度如果n
为零,则模式将被应用尽可能多的次数,数组可以有任何长度,尾随的空字符串将被丢弃。
(强调矿山)
因此在这个配置中,最终的空字符串被丢弃。因此,你只剩下你所拥有的
通常,要将这样的东西标记化,可以使用replaceAll
和split
的组合:
final String[] tokens = input.replaceAll("^\\[|\\]$").split(",");
这将首先去掉起始(^[
)和结束(]$
)括号,然后在,
上拆分。这样,您就不必有某种迟钝的程序逻辑,从任意索引开始循环
另一种选择是,对于更复杂的标记化,可以使用模式
——这可能有些过分,但在编写多个replaceAll
链之前,需要记住这一点
首先,我们需要在正则表达式中定义我们想要的标记(而不是我们正在拆分的标记)——在这种情况下,它很简单,只是数字,所以\d
因此,为了从任意字符串
中提取所有仅数字(无千位/十进制分隔符)值,on将执行以下操作:
final List<Integer> tokens = new ArrayList<>(); <-- to hold the tokens
final Pattern pattern = Pattern.compile("\\d++"); <-- the compiled regex
final Matcher matcher = pattern.matcher(input); <-- the matcher on input
while(matcher.find()) { <-- for each matched token
tokens.add(Integer.parseInt(matcher.group())); <-- parse and `int` and store
}
final List tokens=new ArrayList() 这是因为每个分隔符都有一个“before”和“after”结果,即使它是空的。考虑
882337
你期望这会产生两个结果。
同样地,你期望
882337
生成三个,最后一个为空(假设您的限制足够大,或者假设您使用的几乎是任何其他语言/实现的split()
)。从逻辑上说
,882337
必须生成四个,第一个和最后一个结果为空。这与您的情况完全相同,只是您有多个分隔符。拆分字符串的符号如下:
String test = "[882,337]";
^ ^ ^
因为第一个字符与您的分隔符匹配,所以它留下的所有内容都将是第一个结果。第一个字母的左边是nothing,所以结果是空字符串
由于最后一个符号也与分隔符相匹配,因此结尾可能会出现相同的行为但是:
因此,结果数组中不包括尾随的空字符串
请参阅。拆分从一个对象创建两个(或多个)对象。例如,如果您按拆分a、b
,
您将得到a
和b
但是在”的情况下,b“
您将得到”
和“b”
。你可以这样想:
“
存在于字符串的开头、结尾甚至所有字符之间:
“+”,“+”b“
->”,b“
因此,如果我们在这个”,“
上进行拆分,我们将得到左右部分:”
和“b”
类似的情况发生在“a”
的情况下,最初的结果数组是[“a”,“”]
,但这里split
方法删除尾随的空字符串,只返回[“a”]
(您可以使用split(,,-1)
)来关闭此清除机制
所以如果
String test = "[882,337]";
String[] tokens = test.split("\\[|\\]|,");
您正在拆分:
""+"["+"882"+","+"337"+"]"+""
here: ^ ^ ^
它首先创建数组[“”、“882”、“337”和“”]
,然后删除尾随的空字符串,最后接收到:
[“”、“882”、“337”]
从结果数组的开头删除空字符串的唯一情况是
- 您正在使用Java 8(或更高版本)和正则表达式上的拆分,该正则表达式的长度为零,类似于
split(“”
),或者在每个x
之前使用split((?=x)”)
(更多信息见:)
- 当这个空字符串是split方法的结果时。例如,
“.split(”
将不删除”
,更多信息请参见:
您应该了解如何使用。split()也可以使用简单字符串作为参数进行调用,如“,”。不过,请仔细阅读捕获组String.split(delimiter,0)
带尾随空匹配项-因此这并不完全正确。String test=“,882337;”;String[]tokens=test.split(“,”);System.out.println(令牌长度)代码>产生3Ah,很有趣。谢谢你的解释。在处理这种情况时,我会从索引1开始对数组进行处理,以忽略前面的空字符串,还是有更优雅的方法呢?@SuperCow,如果您确实知道您的分隔符与位置为零的字符串相匹配(resultin