Assumindo as seqüências a e b:
a += b
a = a.concat(b)
Sob o capô, eles são a mesma coisa?
Aqui está concat descompilado como referência. Eu gostaria de poder descompilar o +
operador também para ver o que isso faz.
public String concat(String s) {
int i = s.length();
if (i == 0) {
return this;
}
else {
char ac[] = new char[count + i];
getChars(0, count, ac, 0);
s.getChars(0, i, ac, count);
return new String(0, count + i, ac);
}
}
java
string
concatenation
shsteimer
fonte
fonte
+
pode ser descompilado.StringBuffer
ouStringBuilder
- (thread inseguro, portanto, mais rápido)Respostas:
Não, não exatamente.
Em primeiro lugar, há uma pequena diferença na semântica. Se
a
fornull
, entãoa.concat(b)
lança umNullPointerException
masa+=b
tratará o valor originala
como se fossenull
. Além disso, oconcat()
método aceita apenasString
valores enquanto o+
operador silenciosamente converte o argumento em uma String (usando otoString()
método para objetos). Portanto, oconcat()
método é mais rigoroso no que aceita.Para olhar por baixo do capô, escreva uma classe simples com
a += b;
Agora desmonte com
javap -c
(incluído no Sun JDK). Você deve ver uma listagem incluindo:Então,
a += b
é o equivalente aO
concat
método deve ser mais rápido. No entanto, com mais seqüências, oStringBuilder
método vence, pelo menos em termos de desempenho.O código fonte
String
eStringBuilder
(e sua classe base privada do pacote) está disponível no src.zip do Sun JDK. Você pode ver que está construindo uma matriz de caracteres (redimensionando conforme necessário) e depois descartando-a quando cria a finalString
. Na prática, a alocação de memória é surpreendentemente rápida.Atualização: Como observa Pawel Adamski, o desempenho mudou no HotSpot mais recente.
javac
ainda produz exatamente o mesmo código, mas o compilador de bytecode engana. O teste simples falha completamente porque todo o corpo do código é jogado fora. A somaSystem.identityHashCode
(nãoString.hashCode
) mostra que oStringBuffer
código tem uma pequena vantagem. Sujeito a alterações quando a próxima atualização for lançada ou se você usar uma JVM diferente. Em @lukaseder , uma lista de intrínsecas do HotSpot JVM .fonte
javap -c
uma classe compilada que o utiliza. (. Oh, como na resposta Você só precisa interpretar o bytecode desmontagem, o que não deve ser tão difícil.)StringBuilder
mesmo quando une duas strings? SeString
incluíssem métodos estáticos para concatenar até quatro strings, ou todas as strings em aString[]
, o código poderia anexar até quatro strings com duas alocações de objeto (o resultadoString
e seu respaldochar[]
, nenhum redundante) e qualquer número de strings com três alocações ( oString[]
, o resultadoString
e o suportechar[]
, sendo apenas o primeiro redundante). Como é, o usoStringBuilder
exigirá, na melhor das hipóteses, quatro alocações e a cópia de cada caractere duas vezes.Niyaz está correto, mas também vale a pena notar que o operador + especial pode ser convertido em algo mais eficiente pelo compilador Java. Java possui uma classe StringBuilder que representa uma String mutável e não segura para threads. Ao executar várias concatenações de String, o compilador Java converte silenciosamente
para dentro
que para cordas grandes é significativamente mais eficiente. Tanto quanto eu sei, isso não acontece quando você usa o método concat.
No entanto, o método concat é mais eficiente ao concatenar uma String vazia em uma String existente. Nesse caso, a JVM não precisa criar um novo objeto String e pode simplesmente retornar o existente. Consulte a documentação da concat para confirmar isso.
Portanto, se você está super preocupado com a eficiência, deve usar o método concat ao concatenar cadeias possivelmente vazias e usar + caso contrário. No entanto, a diferença de desempenho deve ser insignificante e você provavelmente nunca deve se preocupar com isso.
fonte
String
- como você diz,concat
tem uma exceção quando concatena um vazioString
.Fiz um teste semelhante ao @marcio, mas com o seguinte loop:
Apenas por uma boa medida, eu joguei
StringBuilder.append()
também. Cada teste foi executado 10 vezes, com 100k repetições para cada execução. Aqui estão os resultados:StringBuilder
ganha as mãos para baixo. O resultado da hora foi 0 na maioria das corridas e a mais longa levou 16ms.a += b
leva cerca de 40000ms (40s) para cada execução.concat
requer apenas 10000ms (10s) por execução.Ainda não descompilei a classe para ver os internos ou executá-lo no profiler, mas suspeito que
a += b
gaste a maior parte do tempo criando novos objetosStringBuilder
e depois convertendo-os novamente emString
.fonte
+
é usado para duas strings, existem casos em que o usoStringBuilder
é melhor do que seriaString.valueOf(s1).concat(s2)
? Alguma idéia de por que os compiladores não usariam o último [ou omitir avalueOf
chamada nos casos em ques1
se sabe que não são nulos]?A maioria das respostas aqui são de 2008. Parece que as coisas mudaram ao longo do tempo. Meus últimos benchmarks feitos com JMH mostram que no Java 8
+
é cerca de duas vezes mais rápido queconcat
.Minha referência:
Resultados:
fonte
String
nunca incluiu uma função estática para formar uma string concatenando os elementos de aString[]
. Usar+
para concatenar 8 strings usando essa função exigiria a construção e o abandono posteriorString[8]
, mas esse seria o único objeto que precisaria ser construído abandonado, enquanto o uso de aStringBuilder
exigiria a construção e o abandono daStringBuilder
instância e pelo menos umchar[]
armazenamento de backup.String.join()
métodos estáticos foram adicionados no Java 8, como wrappers de sintaxe rápidos em toda ajava.util.StringJoiner
classe.+
mudou para usar essas funções?+
para usá-la) exigiria mais do que aquilo que os desenvolvedores Java estão dispostos a mudar, infelizmente.Tom está correto ao descrever exatamente o que o operador + faz. Ele cria um temporário
StringBuilder
, anexa as peças e termina comtoString()
.No entanto, todas as respostas até agora estão ignorando os efeitos das otimizações de tempo de execução do HotSpot. Especificamente, essas operações temporárias são reconhecidas como um padrão comum e são substituídas por códigos de máquina mais eficientes em tempo de execução.
@ marcio: Você criou um micro-benchmark ; com as JVM modernas, essa não é uma maneira válida de codificar o perfil.
A razão pela qual a otimização em tempo de execução é importante é que muitas dessas diferenças de código - mesmo incluindo a criação de objetos - são completamente diferentes quando o HotSpot começa. A única maneira de saber com certeza é criar um perfil do seu código in situ .
Finalmente, todos esses métodos são de fato incrivelmente rápidos. Pode ser um caso de otimização prematura. Se você possui um código que concatena bastante as strings, a maneira de obter velocidade máxima provavelmente não tem nada a ver com quais operadores você escolhe e, em vez disso, com o algoritmo que você está usando!
fonte
Que tal alguns testes simples? Utilizou o código abaixo:
"a + b"
versão executada em 2500ms .a.concat(b)
executado em 1200ms .Testado várias vezes. A
concat()
execução da versão demorou metade do tempo, em média.Esse resultado me surpreendeu porque o
concat()
método sempre cria uma nova string (retorna um "new String(result)
". É sabido que:Por que o compilador não foi capaz de otimizar a criação de strings no código "a + b", sabendo que sempre resultava na mesma string? Isso poderia evitar uma nova criação de string. Se você não acredita na afirmação acima, teste você mesmo.
fonte
Basicamente, existem duas diferenças importantes entre + e o
concat
método.Se você estiver usando o método concat , poderá concatenar seqüências apenas no caso do operador + , também poderá concatenar a sequência com qualquer tipo de dados.
Por exemplo:
Nesse caso, a saída deve ser 10Olá .
No caso acima, você deve fornecer duas seqüências obrigatórias.
A segunda e principal diferença entre + e concat é que:
Caso 1: Suponha que eu concorde as mesmas strings com o operador concat dessa maneira
Nesse caso, o número total de objetos criados no pool é 7 assim:
Caso 2:
Agora vou concatinar as mesmas strings via operador +
No caso acima, o número total de objetos criados é de apenas 5.
Na verdade, quando concatenamos as strings via operador + , ele mantém uma classe StringBuffer para executar a mesma tarefa da seguinte maneira: -
Dessa forma, ele criará apenas cinco objetos.
Então, pessoal, essas são as diferenças básicas entre + e o método concat . Desfrutar :)
fonte
String s="I"+"am"+"good"+"boy"; String s2 = "go".concat("od"); System.out.println(s2 == s2.intern());
impressõestrue
, o que significa"good"
não estava na piscina corda antes de chamarintern()
Por uma questão de completude, eu gostaria de acrescentar que a definição do operador '+' pode ser encontrada no JLS SE8 15.18.1 :
Sobre a implementação, o JLS diz o seguinte:
Portanto, a julgar pelo 'um compilador Java pode usar a classe StringBuffer ou uma técnica semelhante para reduzir', diferentes compiladores podem produzir códigos de bytes diferentes.
fonte
O operador + pode trabalhar entre uma string e um valor de tipo de dados string, char, inteiro, double ou float. Ele apenas converte o valor em sua representação de string antes da concatenação.
O operador concat pode ser feito apenas com e com strings. Ele verifica a compatibilidade do tipo de dados e gera um erro, se não corresponderem.
Exceto isso, o código que você forneceu faz o mesmo.
fonte
Acho que não.
a.concat(b)
é implementado em String e acho que a implementação não mudou muito desde as primeiras máquinas java. A+
implementação da operação depende da versão e compilador Java. Atualmente+
é implementado usandoStringBuffer
para tornar a operação o mais rápido possível. Talvez no futuro isso mude. Nas versões anteriores da+
operação java no Strings, era muito mais lento, pois produzia resultados intermediários.Eu acho que isso
+=
é implementado usando+
e igualmente otimizado.fonte
Ao usar +, a velocidade diminui à medida que o comprimento da string aumenta, mas ao usar concat, a velocidade é mais estável e a melhor opção é usar a classe StringBuilder que possui velocidade estável para fazer isso.
Eu acho que você pode entender o porquê. Mas a melhor maneira de criar seqüências longas é usando StringBuilder () e append (), ou a velocidade será inaceitável.
fonte