Remplacer un caractère à un index spécifique dans une chaîne?

382

J'essaie de remplacer un caractère à un index spécifique dans une chaîne.

Ce que je fais c'est:

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

Cela donne une erreur. Existe-t-il une méthode pour ce faire?

dpp
la source
12
Je me rends compte que cela a été répondu à mort, mais il convient de noter qu'il n'est jamais autorisé d'assigner le résultat d'un appel de fonction en java. Il n'y a pas de choses telles que les références de C (?) Et C ++.
ApproachingDarknessFish
1
@ValekHalfHeart en VB, vous utilisez des parenthèses pour accéder à l'index d'un tableau, cela peut être la raison pour laquelle je suis confus lorsque je commençais en Java: D
dpp
@ApproachingDarknessFish Je ne sais pas trop ce que vous entendez par "il n'est jamais autorisé d'assigner le résultat d'un appel de fonction en java". Vous pouvez sûrement le faire double r = Math.sin(3.14)? Comment est-ce lié à cette question? Merci.
flow2k
1
@ flow2k Oh jeez, vieux commentaire donc je ne peux pas l'éditer mais c'est une faute de frappe, ça devrait dire "il n'est jamais permis d'assigner au résultat d'un appel de fonction en Java". C'est-à-dire que vous pouvez écrire "foo = bar ();" mais jamais "bar () = foo;".
ApproachingDarknessFish
Merci pour la clarification @ApproachingDarknessFish. Je pense qu'il serait étrange d'assigner quelque chose au résultat d'une fonction - y a-t-il des langages qui le permettent réellement? Je me demande quel serait le cas d'utilisation.
flow2k

Réponses:

566

Les chaînes sont immuables en Java. Vous ne pouvez pas les changer.

Vous devez créer une nouvelle chaîne avec le caractère remplacé.

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

Ou vous pouvez utiliser un StringBuilder:

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

System.out.println(myName);
Petar Ivanov
la source
3
Ah, tu veux dire comme la replaceméthode qui ne modifiera pas la chaîne mais retournera juste une nouvelle chaîne?
dpp
1
C'est un peu compliqué Mr.Petar. Est-ce la meilleure façon de procéder? Ah, j'ai déjà entendu parler de StringBuilder, cela fait-il une différence? Cela me donnera-t-il une méthode plus simple?
dpp
158

Transformez la chaîne en un caractère [], remplacez la lettre par un index, puis reconvertissez le tableau en chaîne.

String myName = "domanokz";
char[] myNameChars = myName.toCharArray();
myNameChars[4] = 'x';
myName = String.valueOf(myNameChars);
16 points
la source
1
J'adore cette solution. J'ai fini par changer la 3ème ligne pour être myNameChars [index] = character.toCharArray () [0]; pour simplifier. Belle solution.
Dale
2
il semble beaucoup mieux que l'autre plus laidmyName.substring(0,4)+'x'+myName.substring(5);
user924
C'est beaucoup plus simple
Shiva Acharjee
19

Stringest une classe immuable en java. Toute méthode qui semble la modifier renvoie toujours un nouvel objet chaîne avec modification.

Si vous souhaitez manipuler une chaîne, pensez StringBuilderou StringBuffersi vous avez besoin de la sécurité des threads.

sans nom
la source
12

Je suis d'accord avec Petar Ivanov mais il est préférable de mettre en œuvre de la manière suivante:

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
la source
21
et qu'est-ce qui rend votre solution meilleure?
dpp
6

Comme précédemment répondu ici, les Stringinstances sont immuables . StringBufferet StringBuildersont mutables et adaptés à une telle fin, que vous ayez besoin d'être thread-safe ou non.

Il existe cependant un moyen de modifier une chaîne, mais je ne la recommanderais jamais car elle est dangereuse, peu fiable et elle peut être considérée comme de la triche: vous pouvez utiliser la réflexion pour modifier le chartableau interne que contient l'objet String. La réflexion vous permet d'accéder aux champs et méthodes qui sont normalement cachés dans la portée actuelle (méthodes privées ou champs d'une autre classe ...).

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
la source
4

Vous pouvez remplacer une chaîne, comme suit:

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

Notez que la chaîne myNamese produit sur les deux lignes et sur les deux côtés de la deuxième ligne.

Par conséquent, même si les chaînes peuvent être techniquement immuables, dans la pratique, vous pouvez les traiter comme modifiables en les écrasant.

CodeMed
la source
Je n'ai pas dévalorisé votre réponse mais je dois admettre que j'ai un problème avec le terme "écraser" (bien que je pense que nous sommes d'accord sur le concept derrière). L'objet lui-même reste inchangé. Vous faites simplement que votre variable référence un autre objet. Au fait, il est intéressant de mentionner que vous créez au moins quatre instances String dans votre exemple.
C.Champagne
0

La première chose que j'aurais dû remarquer, c'est que charAtc'est une méthode et lui attribuer une valeur en utilisant le signe égal ne fera rien. Si une chaîne est immuable, la charAtméthode pour modifier l'objet chaîne doit recevoir un argument contenant le nouveau caractère. Malheureusement, la chaîne est immuable. Pour modifier la chaîne, j'avais besoin d'utiliser StringBuilder comme suggéré par M. Petar Ivanov.

dpp
la source
-7

cela fonctionnera

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

Sortie: domaxokz

Diabolus Infernalis
la source
1
bien que je déteste fortement cette méthode d'être autorisée à "modifier" le travail des autres sur ce site StackOverFlow. tout à fait injuste: /
Diabolus Infernalis
2
Erreur de syntaxe. Et même si corrigé, disons que je veux remplacer le premier «o» par «x», le deuxième «o» sera également remplacé.
dpp
2
Cela remplacera tous les personnages qui sont identiques à charAt 4.
Shripad Bhat
1
Problème: myName.replace(myName.charAt(5),'x')vous donnera dxmanxkz, ce qui n'est probablement pas ce qui est requis.
Dawood ibn Kareem