Tout se passe comme prévu, mais procédons étape par étape (j'espère que vous avez du temps).
Selon documentation (et code source ) de split(String regex)
méthode) :
Cette méthode fonctionne comme si elle invoquait la méthode de division à deux arguments avec l'expression donnée et un argument limite de zéro.
Ainsi, lorsque vous invoquez
split(String regex)
vous obtenez réellement le résultat de la split(String regex, int limit)
qui est invoquée d'une certaine manière :
split(regex, 0)
Alors ici limit
est réglé sur 0
.
Vous devez savoir certaines choses sur ce paramètre :
générera au départ un tableau qui ressemblera à ceci :
["foo", "bar", ""]
( "barX"
divisé sur "X"
génère "bar"
y ""
), mais comme split
supprime toutes les chaînes vides à la fin, il retournera
["foo", "bar"]
retournera ["foo", "bar", ""]
Je vais essayer de répondre pour le premier cas,
",".split(",").length
qui, comme expliqué précédemment, est effectivement identique à
",".split(",", 0).length
Cela signifie que nous utilisons une version de split qui ne limite pas la longueur du tableau de résultats, MAIS qui supprime toutes les chaînes vides à la fin, ""
. Vous devez comprendre que lorsque nous nous séparons un chose que nous obtenons toujours deux des choses.
En d'autres termes, si nous divisons "abc"
à la place de b
nous obtiendrons "a"
y "c"
.
La partie délicate est de comprendre que si nous divisons "abc"
sur c
nous obtiendrons "ab" and
""` (chaîne vide).
En utilisant cette logique, si nous divisons ","
en ,
nous obtiendrons ""
y ""
(deux chaînes de caractères vides).
Vous pouvez le vérifier facilement en utilisant
for (String s: ",".split(",", -1))
System.out.println("\""+s+"\"");
qui produira
""
""
Notre tableau de résultats contient donc ["", ""]
.
Mais nous avons mis limit
a 0
Nous avons donc décidé que toutes les chaînes vides seront supprimées. Dans ce cas, le tableau de résultats contient uniquement les chaînes vides à la fin Así que ils seront tous supprimés vous laissant avec un tableau vide []
dont la longueur est 0
.
Pour répondre au cas avec
"".split(",").length
vous devez comprendre que la suppression des chaînes vides de fin n'a de sens que si ces chaînes vides de fin sont le résultat d'un fractionnement (et sont très probablement indésirables) . Donc, s'il n'y avait pas d'endroits sur lesquels nous pourrions nous diviser, il n'y aurait pas de raison de lancer ce processus de "nettoyage". C'est pourquoi, dans le cas où la chaîne de caractères d'origine n'a pas été séparée (elle ne contenait pas de partie correspondant à une regex de l'option split
Les créateurs de Java ont décidé de retourner cette chaîne telle quelle.
Cette information est mentionnée dans la documentation de split(String regex, int limit)
où vous pouvez lire :
Si l'expression ne correspond à aucune partie de l'entrée alors le Le tableau résultant n'a qu'un seul élément, à savoir cette chaîne de caractères .
Vous pouvez également observer ce comportement dans code source de cette méthode (à partir de Java 8) :
2316 public String[] split(String regex, int limit) {
2317 /* fastpath if the regex is a
2318 (1)one-char String and this character is not one of the
2319 RegEx's meta characters ".$|()[{^?*+\\", or
2320 (2)two-char String and the first char is the backslash and
2321 the second is not the ascii digit or ascii letter.
2322 */
2323 char ch = 0;
2324 if (((regex.value.length == 1 &&
2325 ".$|()[{^?*+\\".indexOf(ch = regex.charAt(0)) == -1) ||
2326 (regex.length() == 2 &&
2327 regex.charAt(0) == '\\' &&
2328 (((ch = regex.charAt(1))-'0')|('9'-ch)) < 0 &&
2329 ((ch-'a')|('z'-ch)) < 0 &&
2330 ((ch-'A')|('Z'-ch)) < 0)) &&
2331 (ch < Character.MIN_HIGH_SURROGATE ||
2332 ch > Character.MAX_LOW_SURROGATE))
2333 {
2334 int off = 0;
2335 int next = 0;
2336 boolean limited = limit > 0;
2337 ArrayList<String> list = new ArrayList<>();
2338 while ((next = indexOf(ch, off)) != -1) {
2339 if (!limited || list.size() < limit - 1) {
2340 list.add(substring(off, next));
2341 off = next + 1;
2342 } else { // last one
2343 //assert (list.size() == limit - 1);
2344 list.add(substring(off, value.length));
2345 off = value.length;
2346 break;
2347 }
2348 }
2349 // If no match was found, return this
2350 if (off == 0)
2351 return new String[]{this};
2353 // Add remaining segment
2354 if (!limited || list.size() < limit)
2355 list.add(substring(off, value.length));
2357 // Construct result
2358 int resultSize = list.size();
2359 if (limit == 0) {
2360 while (resultSize > 0 && list.get(resultSize - 1).length() == 0) {
2361 resultSize--;
2362 }
2363 }
2364 String[] result = new String[resultSize];
2365 return list.subList(0, resultSize).toArray(result);
2366 }
2367 return Pattern.compile(regex).split(this, limit);
2368 }
où vous pouvez trouver
if (off == 0)
return new String[]{this};
qui signifie
-
if (off == 0)
- si off
(position à partir de laquelle la méthode doit commencer à chercher la prochaine correspondance possible pour l'expression rationnelle passée en tant que split
argument) est toujours 0
après avoir itéré sur la chaîne entière, cela signifie que la méthode n'a pas trouvé de correspondance, donc la chaîne n'a pas été divisée.
-
return new String[]{this};
dans ce cas, nous retournons simplement un tableau avec les données originales/actuelles ( this
) chaîne.
Desde ","
n'a pas pu être trouvé dans ""
même une fois, "".split(",")
doit retourner un tableau avec un élément (chaîne vide sur laquelle vous avez invoqué split
). Cela signifie que la longueur de ce tableau est 1
.