String replace() devuelve espacio extra en Java




stringbuilder javadocs 8 (4)

Version corta

\0 representa el carácter NUL , no es igual a una cadena vacía "" .

Versión larga

  1. Cuando intenta crear una String con caracteres vacíos char[10] ,

    String input = new String(new char[10]);

    esta String contiene 10 caracteres NUL :

    |NUL|NUL|NUL|NUL|NUL|NUL|NUL|NUL|NUL|NUL|
  2. Cuando llame a input.replace("\0", "hello") , el valor NUL ( \0 ) se reemplazará por hello :

    |hello|hello|hello|hello|hello|hello|hello|hello|hello|hello|
  3. Cuando llama a input.replace("", "hello") , el valor NUL no se reemplazará ya que no coincide con la cadena vacía "" :

    |hello|NUL|hello|NUL|hello|NUL|hello|NUL|hello|NUL|hello|NUL|hello|NUL|hello|NUL|hello|NUL|hello|NUL|hello|

Considerar:

System.out.println(new String(new char[10]).replace("\0", "hello"));

tiene salida:

hellohellohellohellohellohellohellohellohellohello 

pero:

System.out.println(new String(new char[10]).replace("", "hello")); 

tiene salida:

hello hello hello hello hello hello hello hello hello hello

¿De dónde vienen estos espacios extra?


El valor predeterminado de char es \u0000 que también se puede representar como \0 . Así que su new char[10] contiene 10 \0 s.

En la primera declaración claramente reemplaza \0 con "hello" . Pero en la segunda declaración dejas de lado el valor predeterminado. Que su salida IDE elige mostrar como un espacio.


No es un espacio. Así es como su IDE / consola muestra el carácter \0 que se llena el new char[10] forma predeterminada.

No está reemplazando \0 con nada, por lo que permanece en cadena. En lugar de .replace("", "hello") está reemplazando solo una cadena vacía "" . Lo importante es que Java asume que "" existe en:

  • comienzo de la cadena,
  • final de la cadena,
  • y entre cada uno de los personajes.

ya que podemos obtener "abc" con:

"abc" = "" + "a" + "" + "b" + "" + "c" + ""`;
      //^          ^          ^          ^

Ahora .replace("", "hello") reemplaza cada una de esas "" con "hello" , por lo que para la cadena de longitud 10 colocará 11 hello adicionales (no 10 ), sin modificar \0 , que se mostrará en Tu salida como espacios.

Tal vez esto sea más fácil de entender:

System.out.println("aaa".replace("", "X"));
  • vamos a representar cada "" con como | . Obtendremos "|a|a|a|" (note que hay 4 | )
  • por lo tanto, reemplazar "" con X resultará en "XaXaXaX" (pero en su caso, en lugar de a consola, se imprimirá \0 usando un carácter que se verá como un espacio)

Explicación

Está utilizando el método String#replace(CharSequence target, CharSequence replacement) ( documentation ).

Si se invoca con una secuencia de caracteres de destino vacía, replace("", replacement) no reemplazará los elementos en el origen, sino que insertará el reemplazo antes de cada carácter.

Esto se debe a que "" coincide con las posiciones entre los caracteres, no con los propios caracteres. Así que cada posición entre será reemplazada, es decir, se insertará la sustitución .

Ejemplo:

"abc".replace("", "d") // Results in "dadbdcd"

Su cadena contiene solo el valor predeterminado de char en cada posición, es

\0\0\0\0\0\0\0\0\0\0

el uso del método da como resultado:

hello\0hello\0hello\0hello\0hello\0hello\0hello\0hello\0hello\0hello\0

Monitor

Es probable que la consola muestre el carácter \0 como espacios en blanco , mientras que en realidad no es un espacio en blanco sino \0 .

Si pruebo su código en una consola diferente, obtengo:

Confirmando que los caracteres no son espacios sino algo diferente (es decir, \0 ).





char