String replace () возвращает лишнее пространство в Java

Рассматривать:

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

имеет вывод:

hellohellohellohellohellohellohellohellohellohello 

но:

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

имеет вывод:

hello hello hello hello hello hello hello hello hello hello

Откуда берутся эти лишние места?

Вы должны перебрать строку и распечатать каждый символ.

copper.hat 19.08.2018 00:56

@Ferrybig Конечного пробела никогда не было. Первоначальное описание ОП было (предположительно) неверным. См., Например, ideone.com/492Cml.

Radiodef 19.08.2018 04:43
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
В компьютерном программировании биты играют важнейшую роль в представлении и манипулировании данными на двоичном уровне. Побитовые операции...
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Приходилось ли вам сталкиваться с требованиями, в которых вас могли попросить поднять тревогу или выдать ошибку, когда метод Java занимает больше...
Полный курс Java для разработчиков веб-сайтов и приложений
Полный курс Java для разработчиков веб-сайтов и приложений
Получите сертификат Java Web и Application Developer, используя наш курс.
17
2
943
4

Ответы 4

Объяснение

Вы используете метод String#replace(CharSequence target, CharSequence replacement) (документация).

Если вызывается с пустой целевой последовательностью символов replace("", replacement), он будет не заменять элементов в источнике, но вставлятьзамена перед каждым символом.

Это связано с тем, что "" соответствует позициям между символами, а не самим символам. Таким образом, каждая позиция между ними будет заменена, т.е. вставлен замена.

Пример:

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

Ваша строка содержит только значение char по умолчанию в каждой позиции, это

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

Таким образом, использование этого метода приводит к:

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

Отображать

Ваша консоль, вероятно, отображала символ \0 как пробел, хотя на самом деле это не пробел, а \0.

Если я попробую ваш код на другой консоли, я получу:

Подтверждение того, что символы действительно не пробелы, а что-то другое (например, \0).

replace("", ...) также вставляет замену в конец строки. См., Например, ideone.com/492Cml.
Radiodef 19.08.2018 04:45

Это не пространство. Это то, как ваш IDE / console показывает\0 символ, которым new char[10] заполнен по умолчанию.

Вы не заменяете \0 ничем, поэтому он остается в строке. Вместо .replace("", "hello") вы заменяете только пустую строку "". Важно то, что Java предполагает, что "" существует по адресу:

  • начало строки,
  • конец строки,
  • и между каждым из персонажей

поскольку мы можем получить "abc" с помощью:

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

Теперь .replace("", "hello") заменяет каждый из этих "" на "hello", поэтому для строки длиной 10 он поместит дополнительные 11hello (не 10), не изменяя \0, который на выходе будет показано в виде пробелов.


Может быть, это будет легче понять:

System.out.println("aaa".replace("", "X"));
  • давайте представим каждый "" как |. Получим "|a|a|a|" (обратите внимание, что есть 4 |)
  • поэтому замена "" на X приведет к "XaXaXaX" (но в вашем случае вместо a ваша консоль будет печатать \0 с использованием символа, который будет выглядеть как пробел)

Укороченная версия

\0 представляет собой символ NUL, а не пустую строку "".

Длинная версия

  1. Когда вы пытаетесь создать String с пустым char[10] ,:

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

    этот String будет содержать 10 символов NUL:

    |NUL|NUL|NUL|NUL|NUL|NUL|NUL|NUL|NUL|NUL|
    
  2. Когда вы вызываете input.replace("\0", "hello"), значение NUL (\0) будет заменено на hello:

    |hello|hello|hello|hello|hello|hello|hello|hello|hello|hello|
    
  3. Когда вы вызываете input.replace("", "hello"), значение NUL не будет заменено, поскольку оно не соответствует пустой строке "":

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

Значение char по умолчанию - \u0000, которое также может быть представлено как \0. Итак, ваш new char[10] содержит 10 \0.

В первом заявлении вы явно заменяете \0 на "hello". Но во втором заявлении вы опускаете значение по умолчанию. Какие выходные данные IDE выбирают для отображения в виде пробела.

Другие вопросы по теме