Substituir um caractere em um índice específico em uma string?

382

Estou tentando substituir um caractere em um índice específico em uma string.

O que estou fazendo é:

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

Isso dá um erro. Existe algum método para fazer isso?

dpp
fonte
12
Sei que isso foi respondido até a morte, mas vale a pena notar que nunca é permitido atribuir o resultado de uma chamada de função em java. Não existem referências a C (?) E C ++.
ApproachingDarknessFish
11
@ValekHalfHeart em VB, você usa parênteses para o índice de acesso de uma matriz, que pode ser a razão por que estou confuso quando eu estava começando em Java: D
DPP
@ApproachingDarknessFish Não sei o que você quer dizer com "nunca é permitido atribuir o resultado de uma chamada de função em java". Certamente você pode fazer double r = Math.sin(3.14)? Como isso se relaciona com esta questão? Obrigado.
flow2k
11
@ flow2k Oh caramba, comentário de idade, então eu não posso editar, mas isso é um erro de digitação, ele deve dizer que "nunca é permitido para atribuir para o resultado de uma chamada de função em Java". Ou seja, você pode escrever "foo = bar ();" mas nunca "bar () = foo;".
ApproachingDarknessFish
Obrigado pelo esclarecimento @ApproachingDarknessFish. Eu acho que seria estranho atribuir algo ao resultado de uma função - existem linguagens que realmente permitem isso? Gostaria de saber qual seria o caso de uso.
flow2k

Respostas:

566

String são imutáveis ​​em Java. Você não pode mudá-los.

Você precisa criar uma nova string com o caractere substituído.

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

Ou você pode usar um StringBuilder:

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

System.out.println(myName);
Petar Ivanov
fonte
3
Ah, você quer dizer como o replacemétodo que não modifica a string, mas apenas retorna uma nova string?
DPP
11
Isso é meio complicado Sr.Petar. Essa é a melhor maneira de fazer isso? Ah, eu já ouvi falar do StringBuilder antes, isso faz alguma diferença? Isso me dará um método mais fácil?
DPP
158

Transforme a String em um caractere [], substitua a letra pelo índice e depois converta a matriz novamente em uma String.

String myName = "domanokz";
char[] myNameChars = myName.toCharArray();
myNameChars[4] = 'x';
myName = String.valueOf(myNameChars);
16dots
fonte
11
Adoro esta solução. Acabei alterando a terceira linha para ser myNameChars [index] = character.toCharArray () [0]; para simplificação. Ótima solução.
Dale
2
parece muito melhor do que o outro mais feio ummyName.substring(0,4)+'x'+myName.substring(5);
user924
É muito mais simples
Shiva Acharjee 14/03
19

Stringé uma classe imutável em java. Qualquer método que parece modificá-lo sempre retorna um novo objeto de string com modificação.

Se você deseja manipular uma string, considere StringBuilderou StringBuffercaso exija segurança de thread.

sem nome
fonte
12

Concordo com Petar Ivanov, mas é melhor se implementarmos da seguinte maneira:

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
fonte
21
e o que torna sua solução melhor?
dpp
6

Como respondido anteriormente aqui, as Stringinstâncias são imutáveis . StringBuffere StringBuildersão mutáveis ​​e adequados para esse fim, independentemente de você precisar ser seguro ou não.

Existe, no entanto, uma maneira de modificar uma String, mas eu nunca a recomendaria porque é insegura, não confiável e pode ser considerada trapaça: você pode usar a reflexão para modificar a charmatriz interna que o objeto String contém. O Reflection permite acessar campos e métodos normalmente ocultos no escopo atual (métodos ou campos particulares de outra 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.Champanhe
fonte
4

Você pode substituir uma sequência, da seguinte maneira:

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

Observe que a seqüência myNameocorre nas duas linhas e nos dois lados da segunda linha.

Portanto, mesmo que as strings possam ser tecnicamente imutáveis, na prática, você pode tratá-las como editáveis, substituindo-as.

CodeMed
fonte
Não reduzi a sua resposta, mas devo admitir que tenho um problema com o termo "substituir" (embora eu ache que concordamos com o conceito por trás). O objeto em si permanece inalterado. Você acabou de fazer sua variável referenciar outro objeto. A propósito, é interessante mencionar que você cria pelo menos quatro instâncias de String no seu exemplo.
C.Champagne
0

A primeira coisa que eu deveria ter notado é que charAté um método e atribuir valor a ele usando sinal de igual não fará nada. Se uma sequência for imutável, o charAtmétodo, para fazer alterações no objeto, deverá receber um argumento contendo o novo caractere. Infelizmente, a string é imutável. Para modificar a string, eu precisava usar o StringBuilder, conforme sugerido pelo Sr. Petar Ivanov.

dpp
fonte
-7

isso vai funcionar

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

Saída: domaxokz

Diabolus Infernalis
fonte
11
embora eu deteste fortemente esse método de permitir a "editabilidade" do trabalho de outras pessoas neste site StackOverFlow. completamente injusto: /
Diabolus Infernalis
2
Erro de sintaxe. E mesmo se corrigido, digamos que eu queira substituir o primeiro 'o' por 'x', o segundo 'o' também será substituído.
dpp
2
Isso irá substituir todos os caracteres que é o mesmo que charAt 4.
Shripad Bhat
11
Problema: myName.replace(myName.charAt(5),'x')você fornecerá o dxmanxkzque provavelmente não é necessário.
Dawood ibn Kareem