¿Reemplazar un carácter en un índice específico en una cadena?

382

Estoy tratando de reemplazar un carácter en un índice específico en una cadena.

Lo que estoy haciendo es:

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

Esto da un error. ¿Hay algún método para hacer esto?

dpp
fuente
12
Me doy cuenta de que esto ha sido respondido hasta la muerte, pero vale la pena señalar que nunca está permitido asignar el resultado de una llamada de función en Java. No existen cosas como las referencias de C (?) Y C ++.
ApproachingDarknessFish
1
@ValekHalfHeart en VB, usa paréntesis para acceder al índice de una matriz, esa puede ser la razón por la que estoy confundido cuando comencé en Java: D
dpp
@ApproachingDarknessFish No estoy seguro de lo que quiere decir con que "nunca se le permite asignar el resultado de una llamada de función en Java". ¿Seguramente puedes hacer double r = Math.sin(3.14)? ¿Cómo se relaciona con esta pregunta? Gracias.
flow2k
1
@ flow2k Oh Por Dios, viejo comentario por lo que no se puede editar, pero eso es un error tipográfico, se debe decir que "nunca se le permite asignar al resultado de una llamada a la función en Java". Es decir, puedes escribir "foo = bar ();" pero nunca "bar () = foo;".
ApproachingDarknessFish
Gracias por la aclaración @ApproachingDarknessFish. Creo que sería extraño asignar algo al resultado de una función: ¿hay idiomas que realmente lo permitan? Me pregunto cuál sería el caso de uso.
flow2k

Respuestas:

566

Las cadenas son inmutables en Java. No puedes cambiarlos.

Necesita crear una nueva cadena con el carácter reemplazado.

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

O puede usar un StringBuilder:

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

System.out.println(myName);
Petar Ivanov
fuente
3
Ah, ¿te refieres al replacemétodo que no modificará la cadena sino que solo devolverá una nueva cadena?
dpp
1
Eso es un poco complicado Sr.Petar. ¿Es esa la mejor manera de hacerlo? Ah, he oído hablar de StringBuilder antes, ¿eso hace alguna diferencia? ¿Me dará un método más fácil?
dpp
158

Convierta la cadena en un carácter [], reemplace la letra por el índice, luego convierta la matriz nuevamente en una cadena.

String myName = "domanokz";
char[] myNameChars = myName.toCharArray();
myNameChars[4] = 'x';
myName = String.valueOf(myNameChars);
16 puntos
fuente
1
Amo esta solución. Terminé cambiando la tercera línea para que sea myNameChars [index] = character.toCharArray () [0]; para simplificar Buena solución
Dale
2
se ve mucho mejor que el otro más feomyName.substring(0,4)+'x'+myName.substring(5);
usuario924
Es mucho más simple
Shiva Acharjee
19

Stringes una clase inmutable en java. Cualquier método que parece modificarlo siempre devuelve un nuevo objeto de cadena con modificación.

Si desea manipular una cadena, considere StringBuildero StringBufferen caso de que requiera seguridad de subprocesos.

sin nombre
fuente
12

Estoy de acuerdo con Petar Ivanov pero es mejor si implementamos de la siguiente manera:

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);       
}
Leninkumar Koppoju
fuente
21
¿Y qué hace que su solución sea mejor?
dpp
6

Como se respondió anteriormente aquí, las Stringinstancias son inmutables . StringBuffery StringBuilderson mutables y adecuados para tal fin, ya sea que necesite ser seguro para subprocesos o no.

Sin embargo, hay una forma de modificar una Cadena, pero nunca la recomendaría porque no es segura, no es confiable y puede considerarse como trampa: puede usar la reflexión para modificar la charmatriz interna que contiene el objeto Cadena. Reflection le permite acceder a campos y métodos que normalmente están ocultos en el ámbito actual (métodos privados o campos de otra clase ...).

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();
    }
}
C.Champagne
fuente
4

Puede sobrescribir una cadena de la siguiente manera:

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

Tenga en cuenta que la cadena se myNameproduce en ambas líneas y en ambos lados de la segunda línea.

Por lo tanto, aunque las cadenas pueden ser técnicamente inmutables, en la práctica, puede tratarlas como editables sobrescribiéndolas.

CodeMed
fuente
No he rechazado su respuesta, pero debo admitir que tengo un problema con el término "sobrescribir" (aunque creo que estamos de acuerdo con el concepto detrás). El objeto en sí permanece sin cambios. Simplemente hace que su variable haga referencia a otro objeto. Por cierto, será interesante mencionar que crea al menos cuatro instancias de String en su ejemplo.
C.Champagne
0

Lo primero que debería haber notado es que charAtes un método y asignarle valor utilizando el signo igual no hará nada. Si una cadena es inmutable, el charAtmétodo para realizar cambios en el objeto de cadena debe recibir un argumento que contenga el nuevo carácter. Desafortunadamente, la cadena es inmutable. Para modificar la cadena, necesitaba usar StringBuilder como lo sugirió el Sr. Petar Ivanov.

dpp
fuente
-7

esto funcionará

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

Salida: domaxokz

Diabolus Infernalis
fuente
1
aunque detesto fuertemente este método de permitir la "editabilidad" del trabajo de otros en este sitio StackOverFlow. completamente injusto: /
Diabolus Infernalis
2
Error de sintaxis. E incluso si se corrige, digamos que quiero reemplazar la primera 'o' con 'x', la segunda 'o' también se reemplazará.
dpp
2
Esto reemplazará a todos los personajes que son iguales a charAt 4.
Shripad Bhat
1
Problema: myName.replace(myName.charAt(5),'x')le dará dxmanxkz, que probablemente no sea lo que se requiere.
Dawood ibn Kareem