pattern online number example java regex string class core

java - online - Salida confusa de String.split



regex symbols (8)

De JDK 1.7

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.count == 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<String> 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, count)); off = count; 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, count)); // 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); }

Entonces, para este caso, la expresión regular será manejada por el primero if .

Para el primer caso blank.split(",")

// If no match was found, return this if (off == 0) return new String[] { this };

Por lo tanto, esta función devolverá una matriz que contiene un elemento si no coincide.

Para el segundo caso comma.split(",")

List<String> list = new ArrayList<>(); //... 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);

Como se observa, el último ciclo while ha eliminado todos los elementos vacíos al final de la lista, por lo que resultSize es 0 .

No entiendo el resultado de este código:

public class StringDemo{ public static void main(String args[]) { String blank = ""; String comma = ","; System.out.println("Output1: "+blank.split(",").length); System.out.println("Output2: "+comma.split(",").length); } }

Y obtuve el siguiente resultado:

Output1: 1 Output2: 0


De la documentación de Java 1.7

Divide la cadena alrededor de las coincidencias de la expresión regular dada.

El método split () funciona como si invocando el método de división de dos argumentos con la expresión dada y un argumento de límite de cero. Por lo tanto, las cadenas vacías no se incluyen en la matriz resultante.

En el Caso 1, blank.split(",") does not match any part of the input then the resulting array has just one element, namely this String.

It will return entire String. Entonces, la duración será 1 .

En el caso 2 comma.split(",") will return empty.

split() esperando una expresión regular como argumento, devuelve la matriz de resultados para que coincida con esa expresión regular.

Entonces, la longitud es 0

Por ejemplo ( Documentación )

La cadena "boo: and: foo" , produce los siguientes resultados con estas expresiones:

Regex Result : { "boo", "and", "foo" } o { "b", "", ":and:f" }

Parámetros: regex - la expresión regular de delimitación

Devuelve: la matriz de cadenas calculada dividiendo esta cadena alrededor de las coincidencias de la expresión regular dada

Lanza: PatternSyntaxException - si la sintaxis de la expresión regular no es válida


Desde la clase String javadoc para el método public String[] split (String regex) :

Divide esta cadena alrededor de las coincidencias de la expresión regular dada.

Este método funciona como si invocando el método de división de dos argumentos con la expresión dada y un argumento de límite de cero. Por lo tanto, las cadenas vacías no se incluyen en la matriz resultante.

En el primer caso, la expresión no coincide con ninguna parte de la entrada, por lo que obtuvimos una matriz con un solo elemento: la entrada.

En el segundo caso, la expresión coincide con la entrada y la división debe devolver dos cadenas vacías; pero, según javadoc, se descartan (porque están detrás y vacíos).


Documentación:

Para: System.out.println("Output1: "+blank.split(",").length);

La matriz devuelta por este método contiene cada subcadena de esta cadena que termina con otra subcadena que coincide con la expresión dada o finaliza al final de la cadena. Las subcadenas en la matriz están en el orden en que ocurren en esta cadena. Si la expresión no coincide con ninguna parte de la entrada, la matriz resultante tiene solo un elemento, a saber, esta cadena .

Simplemente devolverá toda la cadena, por eso devuelve 1.

Para el segundo caso, String.split descartará el , por lo que el resultado estará vacío.

String.split silently discards trailing separators

ver cuerdas de guayaba explicadas también


La API para el método de división indica que "si la expresión no coincide con ninguna parte de la entrada, entonces la matriz resultante tiene solo un elemento, a saber, esta cadena".

Entonces, como el String en blanco no contiene un ",", se devuelve un String [] con un elemento (es decir, un espacio en blanco).

Para la coma de cadena, "nada" queda de la cadena original, por lo que se devuelve una matriz vacía.

Esta parece ser la mejor solución si desea procesar el resultado devuelto, por ejemplo

String[] splits = aString.split(","); for(String split: splits) { // do something }


Podemos echar un vistazo al código fuente de java.util.regex.Pattern que está detrás de String.split . Camino por el agujero del conejo, el método

public String[] split(CharSequence input, int limit)

es invocado

Entrada ""

Para la entrada "" este método se llama como

String[] parts = split("", 0);

La parte interesante de este método es :

int index = 0; boolean matchLimited = limit > 0; ArrayList<String> matchList = new ArrayList<>(); Matcher m = matcher(input); while(m.find()) { // Tichodroma: this will not happen for our input } // If no match was found, return this if (index == 0) return new String[] {input.toString()};

Y eso es lo que sucede: se devuelve una new String[] {input.toString()} .

Entrada ","

Para la entrada "," la parte intersting es

// Construct result int resultSize = matchList.size(); if (limit == 0) while (resultSize > 0 && matchList.get(resultSize-1).equals("")) resultSize--; String[] result = new String[resultSize]; return matchList.subList(0, resultSize).toArray(result);

Aquí resultSize == 0 y limit == 0 por lo que se devuelve una new String[0] .


Todo sucede de acuerdo con el plan, pero hagámoslo paso a paso (espero que tengas algo de tiempo).

De acuerdo con la documentation (y el código fuente ) del método de split(String regex) :

Este método funciona como si invocando el método de división de dos argumentos con la expresión dada y un argumento de límite de cero.

Entonces cuando invocas

split(String regex)

en realidad está obteniendo el resultado del método split(String regex, int limit) que se invoca de una manera:

split(regex, 0)

Entonces, aquí el limit está establecido en 0 .

Necesitas saber algunas cosas sobre este parámetro:

  • Si el limit es positivo, está limitando la longitud de la matriz de resultados a un número positivo que haya especificado, por lo que "axaxaxaxa".split("x",2) devolverá una matriz, ["a", "axaxaxa"] , no ["a","a","a","a","a"] .
  • Si el limit es 0 entonces no está limitando la longitud de la matriz de resultados. Pero también significa que se eliminarán las cadenas vacías finales. Por ejemplo:

    "fooXbarX".split("X")

    Al principio generará una matriz que se verá así:

    ["foo", "bar", ""]

    ( "barX" dividido en "X" genera "bar" y "" ), pero como split elimina todas las cadenas vacías, devolverá

    ["foo", "bar"]

  • El comportamiento del valor negativo del limit es similar al comportamiento donde el límite se establece en 0 (no limitará la longitud de la matriz de resultados). La única diferencia es que no eliminará las cadenas vacías del final de la matriz de resultados. En otras palabras

    "fooXbarX".split("X",-1)

devolverá ["foo", "bar", ""]

Echemos un vistazo al caso,

",".split(",").length

que (como se explicó anteriormente) es lo mismo que

",".split(",", 0).length

Esto significa que estamos utilizando una versión de división que no limitará la longitud de la matriz de resultados, pero eliminará todas las cadenas vacías finales , "" . Debes entender que cuando dividimos una cosa siempre obtenemos dos cosas.

En otras palabras, si dividimos "abc" en lugar de b , obtendremos "a" y "c" .
La parte difícil es entender que si dividimos "abc" en c obtendremos "ab" y "" (cadena vacía).

Usando esta lógica, si dividimos "," on , obtendremos "" y "" (dos cadenas vacías).

Puede verificarlo usando split con límite negativo:

for (String s: ",".split(",", -1)){ System.out.println("/""+s+"/""); }

que se imprimirá

"" ""

Entonces, como vemos matriz de resultados aquí es al principio ["", ""] .

Pero dado que por defecto estamos usando el limit establecido en 0 , todas las cadenas vacías finales serán eliminadas. En este caso, la matriz de resultados solo contiene cadenas vacías , por lo que se eliminarán todas , lo que le dejará una matriz vacía [] que tiene una longitud de 0 .

Para responder el caso con

"".split(",").length

es necesario que comprenda que la eliminación de cadenas vacías finales solo tiene sentido si tales cadenas finales vacías son el resultado de la división (y probablemente no sean necesarias) .
Por lo tanto, si no hubiera ningún lugar en el que pudiéramos dividirnos, no existe la posibilidad de que se creen cadenas vacías, por lo que no tiene sentido ejecutar este proceso de "limpieza".

Esta información se menciona en la documentación del método split(String regex, int limit) donde se puede leer:

Si la expresión no coincide con ninguna parte de la entrada , la matriz resultante tiene solo un elemento, a saber, esta cadena .

También puede ver este comportamiento en el código fuente de este método (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 }

donde puedes encontrar

if (off == 0) return new String[]{this};

fragmento que significa

  • if (off == 0) - if off (posición desde la cual el método debería comenzar a buscar la siguiente coincidencia posible para regex pasado como argumento de split ) sigue siendo 0 después de iterar sobre una cadena completa, no encontramos ninguna coincidencia, por lo que la cadena fue no dividido
  • return new String[]{this}; - en ese caso devolvamos una matriz con la cadena original (representada por this ).

Como "," no se pudo encontrar en "" ni siquiera una vez, "".split(",") debe devolver una matriz con un elemento (cadena vacía en la que invoca la split ). Esto significa que la longitud de esta matriz es 1 .

Por cierto. Java 8 introdujo otro mecanismo. Elimina las principales cadenas vacías (si se crearon durante el proceso de división) si nos dividimos usando una expresión regular de longitud cero (como "" o con una apariencia aproximada (?<!x) ). Más información en: ¿Por qué en Java 8 split a veces se eliminan cadenas vacías al inicio de la matriz de resultados?


String blank = ""; String comma = ","; System.out.println("Output1: "+blank.split(",").length); // case 1 System.out.println("Output2: "+comma.split(",").length); // case 2

caso 1 - Aquí blank.split(",") devolverá "" porque no hay , en blank obtendrá el mismo, así que la longitud será 1

caso 2- Aquí comma.split(",") devolverá matriz vacía, tienes que escapar , si quieres contar la comma con longitud 1 else longitud será 0

De nuevo comma.split(",") split () esperando una regex como argumento, devolverá la matriz de resultados para que coincida con esa regex .

La matriz devuelta por este método contiene cada subcadena de esta cadena que termina con otra subcadena que coincide con la expresión dada o finaliza al final de la cadena.

Más

Si la expresión no coincide con ninguna parte de la entrada, la matriz resultante tiene solo un elemento, a saber, esta cadena.