我练习阅读输入然后对其进行标记。 例如,如果我有[882,337]我想得到数字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]);
它有点工作,输出是: (空行) 882 337
我不明白为什么令牌[0]为空?我希望只有两个令牌,其中令牌[0] = 882,令牌[1] = 337.
我检查了一些链接,但没有找到答案。
感谢您的帮助!
答案 0 :(得分:6)
拆分拆分给定的String
。如果你split
" [882,337]"在" ["或","或"]"那你实际上有:
但是,正如您调用了String.split(delimiter)
,这会调用String.split(delimiter, limit)
,limit
为零。
limit
参数控制模式的应用次数,因此会影响结果数组的长度。如果限制n
大于零,那么该模式最多会应用n - 1
次,数组的长度不会超过n
,并且数组的数量不会超过n
;最后一个条目将包含除最后一个匹配分隔符之外的所有输入。如果n
是非正数,则模式将被应用尽可能多次,并且数组可以具有任何长度。 如果replaceAll
为零,则模式将被应用尽可能多次,数组可以具有任意长度,并且尾随空字符串将被丢弃。
(强调我的)
因此,在此配置中,最后的空字符串将被丢弃。因此,您将完全拥有所拥有的东西。
通常,为了对这样的内容进行标记,可以选择split
和final String[] tokens = input.replaceAll("^\\[|\\]$").split(",");
的组合:
^[
这将首先剥离开头(]$
)和结束(,
)括号,然后在Pattern
上拆分。这样你就不必有一些有点钝的程序逻辑,你可以从任意索引开始循环。
作为替代方案,对于更复杂的标记化,可以使用replaceAll
- 这里可能有些过分,但在编写多个\d
链之前,请记住这一点。
首先,我们需要在Regex中定义我们想要的令牌(而不是我们要拆分的令牌) - 在这种情况下它很简单,它只是数字所以{{1 }}
因此,为了从任意String
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
}
N.B:我使用占有正则表达式来提高效率
所以,你看,上面的代码比简单的replaceAll().split()
稍微复杂一些,但它更具可扩展性。您可以使用任意复杂的正则表达式来标记almost any输入。
答案 1 :(得分:3)
分割字符串的符号在这里:
String test = "[882,337]";
^ ^ ^
因为第一个字符与您的分隔符匹配,所以从它开始的所有内容都将是第一个结果。好吧,从第一个字母开始就没有了,所以结果是空字符串。
由于最后一个符号也与分隔符匹配,因此可以预期结束时会出现相同的行为。的但强>:
因此,结尾的空字符串不包含在结果数组中。
请参阅Javadoc。
答案 2 :(得分:2)
那是因为每个分隔符都有&#34;之前&#34; &#34;&#34;&#34;&#34;结果,即使它是空的。考虑
882337
您希望产生两个结果。 同样,你期望
882337,
生成三个,最后一个为空(假设你的限制足够大,或者假设你几乎使用split()
的任何其他语言/实现)。从逻辑上扩展,
,882337,
必须产生四个,第一个和最后一个结果为空。这是你的情况,除了你有多个分隔符。
答案 3 :(得分:2)
分裂从一件事中创造出两件(或更多件)的东西。例如,如果您按a,b
分割,
,则会获得a
和b
。
但是如果是",b"
,您将获得""
和"b"
。你可以这样想:
""
存在于字符串的所有字符的开头,结尾甚至中间:
""+","+"b"
- &gt; ",b"
因此,如果我们对此","
进行拆分,我们会左右两部分:""
和"b"
类似的情况发生在"a,"
的情况下,并且第一个结果数组是["a",""]
但是这里split
方法删除尾随空字符串并仅返回["a"]
(您可以关闭这种清算机制使用split(",", -1)
)。
所以
String test = "[882,337]";
String[] tokens = test.split("\\[|\\]|,");
你正在分裂:
""+"["+"882"+","+"337"+"]"+""
here: ^ ^ ^
首先创建数组["", "882", "337", ""]
,然后删除尾随空字符串,最后你收到:
["", "882", "337"]
仅从结果数组的开头删除空字符串的情况是
split("")
,或者在每个x
之前使用split("(?=x)")
说明(更多信息请参阅:{{ 3}})"".split("")
不会删除 ""
,更多信息请点击此处:Why in Java 8 split sometimes removes empty strings at start of result array?