Замінити символ на певний індекс у рядку?


382

Я намагаюся замінити символ на певний індекс в рядку.

Що я роблю, це:

String myName = "domanokz";
myName.charAt(4) = 'x';

Це дає помилку. Чи є якийсь спосіб зробити це?


12
Я усвідомлюю, що на це відповіли смертю, але варто зазначити, що ніколи не дозволяється призначати результат виклику функції в java. Немає таких речей, як посилання на C (?) Та C ++.
Наближається

1
@ ValekHalfHeart у VB, ви використовуєте дужки для доступу до індексу масиву, це може бути причиною, чому я плутаюся, коли я починав на Java: D
dpp

@ApproachingDarknessFish Я не впевнений, що ти маєш на увазі під цим "ніколи не дозволяється призначати результат виклику функції в Java". Звичайно, ви можете зробити double r = Math.sin(3.14)? Як це стосується цього питання? Дякую.
flow2k

1
@ Flow2k О господи, старий коментар , так що я не можу змінити , але це помилка, він повинен сказати , що «він ніколи не дозволяється призначати в результаті виклику функції в Java». Тобто ви можете написати "foo = bar ();" але ніколи "bar () = foo;".
Наближається до

Дякуємо за роз’яснення @ApproachingDarknessFish. Я думаю, було б дивно присвоїти щось результату функції - чи існують мови, які насправді дозволяють це? Цікаво, яким би був випадок використання.
flow2k

Відповіді:


566

Рядок незмінні на Java. Ви не можете їх змінити.

Потрібно створити новий рядок із заміненим символом.

String myName = "domanokz";
String newName = myName.substring(0,4)+'x'+myName.substring(5);

Або ви можете використовувати StringBuilder:

StringBuilder myName = new StringBuilder("domanokz");
myName.setCharAt(4, 'x');

System.out.println(myName);

3
Ах, ти маєш на увазі, як replaceметод, який не змінює рядок, а просто поверне нову рядок?
dpp

1
Це якось складніше містера Петара. Це найкращий спосіб зробити це? Ах, я чув про StringBuilder раніше, чи це має значення? Чи дасть мені простіший метод?
dpp

158

Перетворіть рядок у char [], замініть букву на індекс, а потім перетворіть масив назад у String.

String myName = "domanokz";
char[] myNameChars = myName.toCharArray();
myNameChars[4] = 'x';
myName = String.valueOf(myNameChars);

1
Любіть це рішення. Я змінив 3-й рядок на myNameChars [index] = character.toCharArray () [0]; для спрощення. Приємне рішення.
Дейл

2
це виглядає набагато краще, ніж інші потворнішіmyName.substring(0,4)+'x'+myName.substring(5);
user924

Набагато простіше
Шива Ачарджі

19

Stringє незмінним класом в java. Будь-який метод, який, здається, модифікує його, завжди повертає новий рядковий об'єкт з модифікацією.

Якщо ви хочете маніпулювати рядком, розгляньте StringBuilderчи StringBufferу випадку, якщо вам потрібна безпека нитки.


12

Я погоджуюся з Петром Івановим, але найкраще, якщо ми реалізуємо наступним чином:

public String replace(String str, int index, char replace){     
    if(str==null){
        return str;
    }else if(index<0 || index>=str.length()){
        return str;
    }
    char[] chars = str.toCharArray();
    chars[index] = replace;
    return String.valueOf(chars);       
}

21
і що робить ваше рішення кращим?
dpp

6

Як було сказано раніше, Stringвипадки незмінні . StringBufferі StringBuilderє змінними та підходять для такої мети, чи потрібно вам бути безпечними для ниток чи ні.

Однак є спосіб змінити String, але я ніколи не рекомендував би її, оскільки це небезпечно, ненадійно, і це може вважатися обманом: ви можете використовувати відображення для зміни внутрішнього charмасиву, що містить об'єкт String. Рефлексія дозволяє отримати доступ до полів і методів, які зазвичай приховані в поточному діапазоні (приватні методи або поля з іншого класу ...).

public static void main(String[] args) {
    String text = "This is a test";
    try {
        //String.value is the array of char (char[])
        //that contains the text of the String
        Field valueField = String.class.getDeclaredField("value");
        //String.value is a private variable so it must be set as accessible 
        //to read and/or to modify its value
        valueField.setAccessible(true);
        //now we get the array the String instance is actually using
        char[] value = (char[])valueField.get(text);
        //The 13rd character is the "s" of the word "Test"
        value[12]='x';
        //We display the string which should be "This is a text"
        System.out.println(text);
    } catch (NoSuchFieldException | SecurityException e) {
        e.printStackTrace();
    } catch (IllegalArgumentException e) {
        e.printStackTrace();
    } catch (IllegalAccessException e) {
        e.printStackTrace();
    }
}

4

Ви можете перезаписати рядок таким чином:

String myName = "halftime";
myName = myName.substring(0,4)+'x'+myName.substring(5);  

Зауважте, що рядок myNameзустрічається як в обох, так і в обох сторонах другого рядка.

Тому, хоча рядки технічно можуть бути незмінні, на практиці ви можете вважати їх редагованими, перезаписуючи їх.


Я не відмовився від вашої відповіді, але мушу визнати, що у мене є проблема з терміном "перезаписати" (хоча я думаю, що ми погоджуємося з концепцією, що стоїть). Сам об’єкт залишається незмінним. Ви просто зробите свою змінну посилання іншим об'єктом. До речі, вам цікаво згадати, що ви створюєте принаймні чотири екземпляри String у своєму прикладі.
C.Шампань

0

Перше, що я мав би помітити, це те charAt, що метод і присвоєння йому значення за допомогою знака рівності нічого не дасть. Якщо рядок є незмінною, charAtметод, щоб внести зміни до об'єкта рядка, повинен отримати аргумент, що містить новий символ. На жаль, рядок незмінний. Щоб змінити рядок, мені потрібно було використовувати StringBuilder, як запропонував пан Петр Іванов.


-7

це спрацює

   String myName="domanokz";
   String p=myName.replace(myName.charAt(4),'x');
   System.out.println(p);

Вихід: domaxokz


1
хоча я сильно заперечую, що цей метод дозволяє "редагувати" роботу інших на цьому StackOverFlow сайті. повністю несправедливо: /
Diabolus Infernalis

2
Синтаксична помилка. І навіть якщо виправлено, скажіть, що я хочу замінити перше "o" на "x", друге "o" також буде замінено.
dpp

2
Це замінить усіх персонажів, що збігаються з
charAt

1
Проблема: myName.replace(myName.charAt(5),'x')дасть вам dxmanxkz, що, мабуть, не є тим, що потрібно.
Давуд ібн Карім
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.