文字列の特定のインデックスにある文字を置き換えますか?


382

文字列内の特定のインデックスにある文字を置き換えようとしています。

私がやっていることは:

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

これはエラーになります。これを行う方法はありますか?


12
私はこれが死への答えになっていることを理解していますが、Javaの関数呼び出しの結果を割り当てることは決して許可されていないことに注意する価値があります。C(?)やC ++の参照などはありません。
ApproachingDarknessFish

1
VBの@ValekHalfHeartでは、括弧を使用して配列のインデックスにアクセスします。これが、Javaで起動したときに混乱する理由かもしれません:D
dpp

@ApproachingDarknessFish「Javaでの関数呼び出しの結果を割り当てることは許可されていません」という意味がわかりません。きっとできますdouble r = Math.sin(3.14)か?この質問とどのように関連していますか?ありがとう。
flow2k 2017年

1
@ flow2k、うわあああ、古いコメント私は編集することはできませんが、それはタイプミスですので、それは「割り当てることが許されないことを言うべき Javaで関数呼び出しの結果」。つまり、「foo = bar();」と書くことができます。しかし、決して「bar()= foo;」ではありません。
DarknessFishへの接近

@ApproachingDarknessFishの説明に感謝します。関数の結果に何かを割り当てるのは奇妙だと思います-これを実際に許可する言語はありますか?ユースケースはどうなるのだろう。
flow2k 2017年

回答:


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、2011

1
それはちょっと複雑なミスター・ペタールです。それはあなたがそれをする最良の方法ですか?ああ、私は以前にStringBuilderについて聞いたことがありますが、違いはありますか?それは私にもっと簡単な方法を与えますか?
dpp d'

158

文字列をchar []に変換し、文字をインデックスで置き換えてから、配列を文字列に変換します。

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

はるかに簡単です
Shiva Acharjee

19

StringJavaの不変クラスです。それを変更していると思われるメソッドは常に、変更を加えた新しい文字列オブジェクトを返します。

文字列を操作する場合は、スレッドセーフが必要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、あなたが安全かどうかのスレッドにする必要があるかどうか、そのような目的のために変更可能と適しています。

ただし、文字列を変更する方法はありますが、安全ではなく、信頼性がなく、不正行為と見なされる可能性があるため、私は推奨しません。リフレクションを使用char、文字列オブジェクトに含まれる内部配列を変更できます。リフレクションを使用すると、現在のスコープで通常は非表示になっているフィールドとメソッド(プライベートメソッドまたは別のクラスのフィールド...)にアクセスできます。

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は両方の行と、2行目の両側にあることに注意してください。

したがって、文字列は技術的には不変であっても、実際には、上書きすることで編集可能として扱うことができます。


私はあなたの回答に反対票を投じていませんが、「上書き」という用語に問題があることを認めなければなりません(ただし、その背後にある概念については同意します)。オブジェクト自体は変更されません。変数に別のオブジェクトを参照させるだけです。ちなみに、あなたの例では少なくとも4つのStringインスタンスを作成していることは興味深いです。
C.Champagne 2015年

0

最初に気づくべきことは、それcharAtがメソッドであり、等号を使用してそれに値を割り当てても何も起こらないことです。文字列が不変の場合、文字charAt列オブジェクトを変更するメソッドは、新しい文字を含む引数を受け取る必要があります。残念ながら、文字列は不変です。文字列を変更するには、Petar Ivanov氏の提案に従って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」で置き換えたいと言っても、2番目の「o」も置き換えられます。
dpp

2
これは、のcharAt 4と同じであるすべての文字に置き換えられます
Shripad Bhatさん

1
問題:myName.replace(myName.charAt(5),'x')はを提供しますがdxmanxkz、これはおそらく必要なことではありません。
Dawood ibnカリーム2017年
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.