Prefácio
Entre os desenvolvedores de Java, a alta ocupação de recursos de strings geralmente é um tópico quente.
Vamos discutir em profundidade por que ocupa altos recursos.
Em Java, um objeto de string é imutável, o que significa que, uma vez criado, você não pode mais alterá -lo. Então, quando secamos cordas, criamos uma nova corda e a antiga é marcada pelo coletor de lixo.
Se processarmos milhões de cordas, geramos milhões de seqüências adicionais a serem processadas pelo coletor de lixo.
Na maioria dos tutoriais, você pode ver que o uso de sinais + para unir strings gerará várias seqüências, resultando em mau desempenho. Recomenda -se usar StringBuffer/StringBuilder para unir.
Mas esse é realmente o caso?
Este artigo fez o experimento a seguir no JDK8:
public static void main (string [] args) {string result = ""; resultado += "mais alguns dados"; System.out.println (resultado); }Decompilar através de javap -c para obter:
Código: 0: aload_0 // empurre 'this' para a pilha 1: Invokespecial #1 // Invoque o construtor da classe de objeto // pop 'this' Ref da pilha 4: retornar // retornar do construtor public static void main (java.lang.string []); Código: 0: LDC #2 // Carregar constante #2 na pilha 2: store_1 // crie um var local a partir da pilha (pop #2) 3: novo #3 // empurre o novo Stringbuilder Refour na pilha 6: DUP // Duplicate Value no topo da pilha 7: Invokespecial #4 // Invoke String Strings InvokeVirtual #5 // Invoke Método Stringbuilder.append () // Pop Obj Referência + Parâmetro // Push Result (StringBuilder Ref) 14: LDC #6 // Push "mais dados" no Stack 16: InvokeVirtual #5 // Invoke Stringbuilder.Append // Pop Twice, Push 19 22: store_1 // Crie Var local a partir da pilha (pop #6) 23: getStatic #8 // Push Value System.out: printStream 26: aload_1 // empurre a variável local contendo #6 27: InvokeVirtual #9 // Invoke PrintStream.println () // POP duas vezes (objeto Ref + Parameter) 30: Return // Return // Return // Return // Method Method MetodStream.println () // Pop duas
Você pode ver que o compilador Java otimiza o bytecode gerado, cria automaticamente um StringBuilder e executa operações de anexos.
Como as substâncias da sequência final já são conhecidas no momento da compilação, o compilador Java executará a otimização acima neste caso. Essa otimização é chamada de otimização de concatenação de string estática e foi ativada desde o JDK5.
Isso significa que, após o JDK5, não precisamos mais gerar manualmente o StringBuilder, e podemos alcançar o mesmo desempenho através do sinal +?
Vamos tentar strings dinamicamente de emenda:
Strings dinâmicos de emenda referem -se a substringas conhecidas apenas em tempo de execução. Por exemplo, adicionando uma string a um loop:
public static void main (string [] args) {string result = ""; for (int i = 0; i <10; i ++) {resultado+= "alguns mais dados"; } System.out.println (resultado); }Também decompilado:
Código: 0: aload_0 // empurre 'this' para a pilha 1: Invokespecial #1 // Invoque o construtor da classe de objeto // pop 'this' Ref da pilha 4: retornar // retornar do construtor public static void main (java.lang.string []); Código: 0: ldc #2 // Carregar constante #2 na pilha 2: store_1 // crie var local a partir da pilha, pop #2 3: iconst_0 // Pressione Valor 0 na pilha 4: iStore_2 // POP Valor e armazene -o no Var 5: iload_2 // Push para a pista 6: i2: i2: i2: i2 / push) push // push a push // picau 6: i2: i2: i2: i2 / push) push // push a push // pica de pista 6: i2: i2: i2: i2 / purt) (push) push // push (push a push to double // da pista 6: i2: i2: i2: i2 / purt) (push a push a push // // pout staw ldc2_w #3 // empurre a constante 10e6 até a pilha 10: dcmpg // compare duas duplas na parte superior da pilha // pop duas vezes, push resultado: -1, 0 ou 1 11: se ramário 40 // se o valor da pilha é maior: Top of the Stack 18: Invokespial #6 // Invoke StringBuilder construtor // Referência do objeto pop 21: aload_1 // empurre o local var 1 (string vazia) // para a pilha 22: InvokeVirtual #7 // Invoke StringBuilder.AppEnd // Pop OBJ Ref, em Push, Result 25: ADC #8 // Stringbuilder.append // pop obj ref + param, push resultado 30: Invokevirtual #9 // Invoke StringBuilder.ToString // Referência de objeto pop 33: store_1 // Crie Var local a partir de pilha (pop) 34: iinc 2, 1 // inclemente Local Variable 2 por 1 37: GoTo 5 // Move para a Instrução em 5 40 40 40 40 40 40 40 40 40 40: Aload_1 // Push Local Var 1 (String de resultado) 44: InvokeVirtual #11 // Invoke Método PrintStream.println () // POP duas vezes (Objeto Ref + Parâmetro) 47: Retorno // Retorno vazio do método
Você pode ver que o StringBuilder era novo aos 14 anos, mas aos 37 anos, o Goto 5. Durante o loop, a otimização não foi alcançada e novos Stringbuilders estavam sendo constantemente gerados.
Portanto, o código acima é semelhante:
String result = ""; para (int i = 0; i <10; i ++) {stringbuilder tmp = new StringBuilder (); tmp.append (resultado); tmp.append ("alguns mais dados"); resultado = tmp.toString ();} System.out.println (resultado);Você pode ver que os novos stringbuilders são gerados constantemente e, através da toque, o StringBuilder original não será mais referenciado, pois o lixo e também aumenta o custo do GC.
Portanto, no uso real, quando você não pode distinguir se uma string é estática ou dinâmica, use StringBuilder.
Referência:
http://www.pellegrino.link/2015/08/22/string-concatenation-with-java-8.html
Resumir
O acima é o conteúdo inteiro deste artigo. Espero que o conteúdo deste artigo tenha certo valor de referência para o estudo ou trabalho de todos. Se você tiver alguma dúvida, pode deixar uma mensagem para se comunicar. Obrigado pelo seu apoio ao wulin.com.