Java – split(regex,limit)方法实际上如何工作?

我试图理解拆分方法是如何工作的,并对它有一点点混淆。 在oracle的文档页面中给出的这个例子中,

String str = "boo:and:foo"; String[] str1 = str.split("o",2); Output b o:and:foo 

这很容易理解,字符串在第一个’o’的出现时就已被字面划分了

但对于

 String[] str1 = str.split("o",3); Output: b :and:foo 

这是怎么出来的?

我从文档中了解到:

limit参数控制模式的应用次数,因此会影响结果数组的长度。 如果限制n大于零,那么模式将最多应用n – 1次,数组的长度将不大于n,并且数组的最后一个条目将包含超出最后一个匹配分隔符的所有输入 。 如果n是非正数,那么模式将被应用尽可能多的次数,并且数组可以具有任何长度。 如果n为零,那么模式将被应用尽可能多的次数,该数组可以具有任何长度,并且将丢弃尾随的空字符串。

这意味着在字符串s上设计或剪切到n次,因此让我们逐一分析以更好地理解:

限制1

 String[] spl1 = str.split("o", 1); 

这意味着将它分割或剪切在字符串o上的一个字符串上,在这种情况下,您将获得所有输入:

 [boo:and:foo] 1 

限制2

 String[] spl1 = str.split("o", 2); 

这意味着在o上减少一次,所以我会在第一个o中断

  boo:and:foo -----^ 

在这种情况下,您将得到两个结果:

 [b,o:and:foo] 1 2 

限制3

 String[] spl1 = str.split("o", 3); 

这意味着在第一个o和第二个o上切两次

  boo:and:foo 1----^^--------------2 

在这种情况下,您将得到三个结果:

 [b, ,:and:foo] 1 2 3 

限制4

 String[] spl1 = str.split("o", 4); 

这意味着在第一,第二和第三o上三次削减它

  boo:and:foo 1_____^^ ^ |___2 |___3 

在这种情况下,您将得到四个结果:

 [b, ,:and:f,o] 1 2 3 4 

限制5

 String[] spl1 = str.split("o", 5); 

这意味着在第一,第二,第三和第四次切割它四次

  boo:and:foo 1_____^^ ^^ |___2 ||___4 |____3 

在这种情况下,您将获得五个结果:

 [b, ,:and:f, , ] 1 2 3 4 5 

只是一个简单的动画来了解更多:

split()方法实际上如何工作?

第二个参数表示模式需要应用的次数。

来自Java Docs:

limit参数控制模式的应用次数,因此会影响结果数组的长度。 如果限制n大于零,那么模式将最多应用n – 1次,数组的长度将不大于n,并且数组的最后一个条目将包含超出最后一个匹配分隔符的所有输入。 如果n是非正数,那么模式将被应用尽可能多的次数,并且数组可以具有任何长度。 如果n为零,那么模式将被应用尽可能多的次数,该数组可以具有任何长度,并且将丢弃尾随的空字符串。

例:

1)如果限制设置为零(str.split(“o”,0))那么根据java docs,模式将被应用尽可能多次,因此结果将是:

[b ,,:和:f]

2)但是如果你将限制设置为非零值(例如1或2),那么模式将被应用n-1次(例如,对于限制1模式将应用0次,对于2将应用1次)所以结果如下:

[boo:and:foo] //为str.split(“o”,1)应用了0次。

[b,o:和:foo] //为str.split(“o”,2)应用了1次。

[b ,,::和foo] //为str.split(“o”,3)应用2次。

第二个参数是正则表达式应用于字符串的次数。 因此,如果限制为3,您将获得b,,:and:foo:在模式出现的位置将字符串拆分为令牌。 请注意,限制可能大于实际字符串中正则表达式的出现次数。

 String[] split(String regex, int limit) 

第二个参数限制拆分后返回的字符串数。

例如, split("anydelimiter", 3)将返回仅3个字符串的数组,即使字符串中的分隔符超过3次。

如果限制为负,则返回的数组将具有尽可能多的子字符串,但是当限制为零时,返回的数组将具有排除尾随空字符串的所有子字符串。

方法请求两个参数split(String regex, int limit)
regex – 分隔正则表达式;
limit – 结果阈值。

Java文档

 **regex** − the delimiting regular expression String Str = new String("boo:and:foo:com:boo"); System.out.println("Return value1: "); for (String retval : Str.split(":", 2)) { System.out.println(retval); } System.out.println(); System.out.println("Return value2: "); for (String retval : Str.split(":", 3)) { System.out.println(retval); } System.out.println(); System.out.println("Return value3: "); for (String retval : Str.split(":", 0)) { System.out.println(retval); } System.out.println(); System.out.println("Return value4: "); for (String retval : Str.split(":")) { System.out.println(retval); } } 

你自己测试每个值1,2,3,4

这是限制的文档

 

The limit parameter controls the number of times the * pattern is applied and therefore affects the length of the resulting * array. If the limit n is greater than zero then the pattern * will be applied at most n - 1 times, the array's * length will be no greater than n, and the array's last entry * will contain all input beyond the last matched delimiter. If n * is non-positive then the pattern will be applied as many times as * possible and the array can have any length. If n is zero then * the pattern will be applied as many times as possible, the array can * have any length, and trailing empty strings will be discarded.

和String类的split方法的源代码。

  public String[] split(String regex, int limit) { /* fastpath if the regex is a (1)one-char String and this character is not one of the RegEx's meta characters ".$|()[{^?*+\\", or (2)two-char String and the first char is the backslash and the second is not the ascii digit or ascii letter. */ char ch = 0; if (((regex.value.length == 1 && ".$|()[{^?*+\\".indexOf(ch = regex.charAt(0)) == -1) || (regex.length() == 2 && regex.charAt(0) == '\\' && (((ch = regex.charAt(1))-'0')|('9'-ch)) < 0 && ((ch-'a')|('z'-ch)) < 0 && ((ch-'A')|('Z'-ch)) < 0)) && (ch < Character.MIN_HIGH_SURROGATE || ch > Character.MAX_LOW_SURROGATE)) { int off = 0; int next = 0; boolean limited = limit > 0; ArrayList list = new ArrayList<>(); while ((next = indexOf(ch, off)) != -1) { if (!limited || list.size() < limit - 1) { list.add(substring(off, next)); off = next + 1; } else { // last one //assert (list.size() == limit - 1); list.add(substring(off, value.length)); off = value.length; break; } } // If no match was found, return this if (off == 0) return new String[]{this}; // Add remaining segment if (!limited || list.size() < limit) list.add(substring(off, value.length)); // Construct result int resultSize = list.size(); if (limit == 0) while (resultSize > 0 && list.get(resultSize - 1).length() == 0) resultSize--; String[] result = new String[resultSize]; return list.subList(0, resultSize).toArray(result); } return Pattern.compile(regex).split(this, limit); } 

看到这部分代码

  boolean limited = limit > 0; ArrayList list = new ArrayList<>(); while ((next = indexOf(ch, off)) != -1) { if (!limited || list.size() < limit - 1) { list.add(substring(off, next)); off = next + 1; } else { // last one //assert (list.size() == limit - 1); list.add(substring(off, value.length)); off = value.length; break; } } 

结果列表大小将是最大限度。