Ein Zeichen an einem bestimmten Index in einer Zeichenfolge ersetzen?

382

Ich versuche, ein Zeichen an einem bestimmten Index in einer Zeichenfolge zu ersetzen.

Was ich tue ist:

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

Dies gibt einen Fehler. Gibt es eine Methode, um dies zu tun?

dpp
quelle
12
Mir ist klar, dass dies zu Tode beantwortet wurde, aber es ist erwähnenswert, dass es niemals erlaubt ist, das Ergebnis eines Funktionsaufrufs in Java zuzuweisen. Es gibt keine Referenzen wie C (?) Und C ++.
Annäherung an
1
@ValekHalfHeart in VB verwenden Sie Klammern, um auf den Index eines Arrays zuzugreifen. Dies kann der Grund sein, warum ich verwirrt bin, als ich in Java angefangen habe: D
dpp
@ApproachingDarknessFish Ich bin mir nicht sicher, was Sie damit meinen, dass es "niemals erlaubt ist, das Ergebnis eines Funktionsaufrufs in Java zuzuweisen". Sicher können Sie tun double r = Math.sin(3.14)? Wie hängt es mit dieser Frage zusammen? Vielen Dank.
flow2k
1
@ flow2k Oh jeez, alter Kommentar so kann ich nicht bearbeiten , sondern dass ein Tippfehler ist, sollte es sagen , dass „es nie zuweisen darf auf das Ergebnis eines Funktionsaufruf in Java“. Dh du kannst schreiben "foo = bar ();" aber niemals "bar () = foo;".
Annäherung an
Vielen Dank für die Klarstellung @ApproachingDarknessFish. Ich denke, es wäre seltsam, dem Ergebnis einer Funktion etwas zuzuweisen - gibt es Sprachen, die dies tatsächlich zulassen? Ich frage mich, was der Anwendungsfall wäre.
flow2k

Antworten:

566

Zeichenfolgen sind in Java unveränderlich. Sie können sie nicht ändern.

Sie müssen eine neue Zeichenfolge erstellen, wobei das Zeichen ersetzt wird.

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

Oder Sie können einen StringBuilder verwenden:

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

System.out.println(myName);
Petar Ivanov
quelle
3
Ah, du meinst wie die replaceMethode, die den String nicht ändert, sondern nur einen neuen String zurückgibt?
dpp
1
Das ist ein bisschen kompliziert, Mr. Petar. Ist das der beste Weg, es zu tun? Ah, ich habe schon mal von StringBuilder gehört, macht das einen Unterschied? Wird es mir eine einfachere Methode geben?
dpp
158

Verwandeln Sie den String in ein Zeichen [], ersetzen Sie den Buchstaben durch einen Index und konvertieren Sie das Array zurück in einen String.

String myName = "domanokz";
char[] myNameChars = myName.toCharArray();
myNameChars[4] = 'x';
myName = String.valueOf(myNameChars);
16 Punkte
quelle
1
Ich liebe diese Lösung. Am Ende habe ich die 3. Zeile in myNameChars [index] = character.toCharArray () [0] geändert. zur Vereinfachung. Schöne Lösung.
Dale
2
es sieht viel besser aus als das andere hässlicheremyName.substring(0,4)+'x'+myName.substring(5);
user924
Es ist viel einfacher
Shiva Acharjee
19

Stringist eine unveränderliche Klasse in Java. Jede Methode, die sie zu ändern scheint, gibt immer ein neues Zeichenfolgenobjekt mit Änderung zurück.

Wenn Sie eine Zeichenfolge manipulieren möchten, ziehen Sie dies in Betracht StringBuilderoder StringBufferfalls Sie Thread-Sicherheit benötigen.

kein Name
quelle
12

Ich stimme Petar Ivanov zu, aber es ist am besten, wenn wir Folgendes umsetzen:

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
quelle
21
und was macht Ihre Lösung besser?
dpp
6

Wie hier bereits beantwortet, sind StringInstanzen unveränderlich . StringBufferund StringBuildersind veränderlich und für einen solchen Zweck geeignet, unabhängig davon, ob Sie threadsicher sein müssen oder nicht.

Es gibt jedoch eine Möglichkeit, einen String zu ändern, aber ich würde ihn niemals empfehlen, da er unsicher und unzuverlässig ist und als Betrug angesehen werden kann: Sie können Reflektion verwenden , um das innere charArray zu ändern, das das String-Objekt enthält. Mit Reflection können Sie auf Felder und Methoden zugreifen, die normalerweise im aktuellen Bereich verborgen sind (private Methoden oder Felder einer anderen Klasse ...).

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. Champagner
quelle
4

Sie können eine Zeichenfolge wie folgt überschreiben:

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

Beachten Sie, dass die Zeichenfolge myNamein beiden Zeilen und auf beiden Seiten der zweiten Zeile vorkommt.

Obwohl Zeichenfolgen technisch unveränderlich sein können, können Sie sie in der Praxis als bearbeitbar behandeln, indem Sie sie überschreiben.

CodeMed
quelle
Ich habe Ihre Antwort nicht abgelehnt, aber ich muss zugeben, dass ich ein Problem mit dem Begriff "Überschreiben" habe (obwohl ich denke, dass wir uns über das dahinter stehende Konzept einig sind). Das Objekt selbst bleibt unverändert. Sie lassen Ihre Variable einfach auf ein anderes Objekt verweisen. Übrigens ist es interessant zu erwähnen, dass Sie in Ihrem Beispiel mindestens vier String-Instanzen erstellen.
C.Champagne
0

Das erste, was ich hätte bemerken müssen, ist, dass charAtes sich um eine Methode handelt und das Zuweisen eines Werts mit Gleichheitszeichen nichts bewirkt. Wenn eine Zeichenfolge unveränderlich ist, muss die charAtMethode zum Ändern des Zeichenfolgenobjekts ein Argument erhalten, das das neue Zeichen enthält. Leider ist die Zeichenfolge unveränderlich. Um die Zeichenfolge zu ändern, musste ich StringBuilder verwenden, wie von Herrn Petar Ivanov vorgeschlagen.

dpp
quelle
-7

das wird funktionieren

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

Ausgabe: domaxokz

Diabolus Infernalis
quelle
1
obwohl ich diese Methode, "Bearbeitbarkeit" der Arbeit anderer auf dieser StackOverFlow-Site zuzulassen, sehr verabscheue. völlig unfair: /
Diabolus Infernalis
2
Syntax-Fehler. Und selbst wenn korrigiert, sagen wir, ich möchte das erste 'o' durch 'x' ersetzen, wird auch das zweite 'o' ersetzt.
dpp
2
Dies wird alle Zeichen ersetzen, die mit charAt 4 identisch sind.
Shripad Bhat
1
Problem: myName.replace(myName.charAt(5),'x')wird Ihnen geben dxmanxkz, was wahrscheinlich nicht das ist, was benötigt wird.
Dawood ibn Kareem