Pergunta

Existe uma diferença perceptível entre usando String.format e concatenação de String em Java?

I tendem a usar String.format mas ocasionalmente vai escorregar e usar uma concatenação. Eu queria saber se era melhor que o outro.

A forma como eu vejo, String.format lhe dá mais poder em "formatar" o string; e meios de concatenação você não precisa se preocupar com acidentalmente colocar em um extra% s ou em falta para fora.

String.format também é mais curto.

Qual deles é mais legível depende de como funciona a sua cabeça.

Foi útil?

Solução

Eu sugiro que é melhor prática para uso String.format(). A principal razão é que String.format() pode ser mais facilmente localizados com texto carregado a partir de arquivos de recursos enquanto concatenação não pode ser localizado, sem produzir um novo executável com código diferente para cada idioma.

Se você está pensando em seu aplicativo sendo localisable você também deve adquirir o hábito de especificar posições de argumento para o seu formato de fichas, bem como:

"Hello %1$s the time is %2$t"

Este pode então ser localizada e tem o nome eo tempo fichas trocados sem a necessidade de uma recompilação do executável para a conta para os diferentes ordenação. Com posições argumento que você também pode voltar a usar o mesmo argumento sem passá-la para a função duas vezes:

String.format("Hello %1$s, your name is %1$s and the time is %2$t", name, time)

Outras dicas

Sobre o desempenho:

public static void main(String[] args) throws Exception {      
  long start = System.currentTimeMillis();
  for(int i = 0; i < 1000000; i++){
    String s = "Hi " + i + "; Hi to you " + i*2;
  }
  long end = System.currentTimeMillis();
  System.out.println("Concatenation = " + ((end - start)) + " millisecond") ;

  start = System.currentTimeMillis();
  for(int i = 0; i < 1000000; i++){
    String s = String.format("Hi %s; Hi to you %s",i, + i*2);
  }
  end = System.currentTimeMillis();
  System.out.println("Format = " + ((end - start)) + " millisecond");
}

Os resultados de tempo são como se segue:

  • A concatenação = 265 milissegundos
  • Format = 4141 milissegundos

Portanto, a concatenação é muito mais rápido do que String.format.

Uma vez que há uma discussão sobre o desempenho Pensei em adicionar em uma comparação que incluiu StringBuilder. É, de facto, mais rápido do que o concat e, naturalmente, a opção String.format.

Para fazer este uma espécie de maçãs com maçãs comparação eu instanciar um novo StringBuilder no circuito e não fora (este é realmente mais rápido do que fazer apenas uma instanciação provavelmente devido à sobrecarga de espaço alocação de re-para o acréscimo looping em o fim de um construtor).

    String formatString = "Hi %s; Hi to you %s";

    long start = System.currentTimeMillis();
    for (int i = 0; i < 1000000; i++) {
        String s = String.format(formatString, i, +i * 2);
    }

    long end = System.currentTimeMillis();
    log.info("Format = " + ((end - start)) + " millisecond");

    start = System.currentTimeMillis();

    for (int i = 0; i < 1000000; i++) {
        String s = "Hi " + i + "; Hi to you " + i * 2;
    }

    end = System.currentTimeMillis();

    log.info("Concatenation = " + ((end - start)) + " millisecond");

    start = System.currentTimeMillis();

    for (int i = 0; i < 1000000; i++) {
        StringBuilder bldString = new StringBuilder("Hi ");
        bldString.append(i).append("; Hi to you ").append(i * 2);
    }

    end = System.currentTimeMillis();

    log.info("String Builder = " + ((end - start)) + " millisecond");
  • 2012-01-11 16: 30: 46,058 INFO [TestMain] - Format = 1416 milissegundos
  • 2012-01-11 16: 30: 46,190 INFO [TestMain] - A concatenação = 134 milissegundos
  • 2012-01-11 16: 30: 46,313 INFO [TestMain] - corda Builder = 117 milissegundos

Um problema com .format é que você perde a segurança de tipo estático. Você pode ter muito poucos argumentos para o seu formato, e você pode ter os tipos errados para os especificadores de formato - tanto levando a um IllegalFormatException em tempo de execução , então você pode acabar com o registo de código que a produção breaks <. / p>

Em contraste, os argumentos para + pode ser testado pelo compilador.

Qual deles é mais legível depende de como funciona a sua cabeça.

Você tem sua resposta ali.

É uma questão de gosto pessoal.

concatenação de String é marginalmente mais rápido, eu suponho, mas que deve ser insignificante.

Aqui está um teste com vários tamanhos de amostra em milissegundos.

public class Time {

public static String sysFile = "/sys/class/camera/rear/rear_flash";
public static String cmdString = "echo %s > " + sysFile;

public static void main(String[] args) {

  int i = 1;
  for(int run=1; run <= 12; run++){
      for(int test =1; test <= 2 ; test++){
        System.out.println(
                String.format("\nTEST: %s, RUN: %s, Iterations: %s",run,test,i));
        test(run, i);
      }
      System.out.println("\n____________________________");
      i = i*3;
  }
}

public static void test(int run, int iterations){

      long start = System.nanoTime();
      for( int i=0;i<iterations; i++){
          String s = "echo " + i + " > "+ sysFile;
      }
      long t = System.nanoTime() - start;   
      String r = String.format("  %-13s =%10d %s", "Concatenation",t,"nanosecond");
      System.out.println(r) ;


     start = System.nanoTime();       
     for( int i=0;i<iterations; i++){
         String s =  String.format(cmdString, i);
     }
     t = System.nanoTime() - start; 
     r = String.format("  %-13s =%10d %s", "Format",t,"nanosecond");
     System.out.println(r);

      start = System.nanoTime();          
      for( int i=0;i<iterations; i++){
          StringBuilder b = new StringBuilder("echo ");
          b.append(i).append(" > ").append(sysFile);
          String s = b.toString();
      }
     t = System.nanoTime() - start; 
     r = String.format("  %-13s =%10d %s", "StringBuilder",t,"nanosecond");
     System.out.println(r);
}

}

TEST: 1, RUN: 1, Iterations: 1
  Concatenation =     14911 nanosecond
  Format        =     45026 nanosecond
  StringBuilder =      3509 nanosecond

TEST: 1, RUN: 2, Iterations: 1
  Concatenation =      3509 nanosecond
  Format        =     38594 nanosecond
  StringBuilder =      3509 nanosecond

____________________________

TEST: 2, RUN: 1, Iterations: 3
  Concatenation =      8479 nanosecond
  Format        =     94438 nanosecond
  StringBuilder =      5263 nanosecond

TEST: 2, RUN: 2, Iterations: 3
  Concatenation =      4970 nanosecond
  Format        =     92976 nanosecond
  StringBuilder =      5848 nanosecond

____________________________

TEST: 3, RUN: 1, Iterations: 9
  Concatenation =     11403 nanosecond
  Format        =    287115 nanosecond
  StringBuilder =     14326 nanosecond

TEST: 3, RUN: 2, Iterations: 9
  Concatenation =     12280 nanosecond
  Format        =    209051 nanosecond
  StringBuilder =     11818 nanosecond

____________________________

TEST: 5, RUN: 1, Iterations: 81
  Concatenation =     54383 nanosecond
  Format        =   1503113 nanosecond
  StringBuilder =     40056 nanosecond

TEST: 5, RUN: 2, Iterations: 81
  Concatenation =     44149 nanosecond
  Format        =   1264241 nanosecond
  StringBuilder =     34208 nanosecond

____________________________

TEST: 6, RUN: 1, Iterations: 243
  Concatenation =     76018 nanosecond
  Format        =   3210891 nanosecond
  StringBuilder =     76603 nanosecond

TEST: 6, RUN: 2, Iterations: 243
  Concatenation =     91222 nanosecond
  Format        =   2716773 nanosecond
  StringBuilder =     73972 nanosecond

____________________________

TEST: 8, RUN: 1, Iterations: 2187
  Concatenation =    527450 nanosecond
  Format        =  10291108 nanosecond
  StringBuilder =    885027 nanosecond

TEST: 8, RUN: 2, Iterations: 2187
  Concatenation =    526865 nanosecond
  Format        =   6294307 nanosecond
  StringBuilder =    591773 nanosecond

____________________________

TEST: 10, RUN: 1, Iterations: 19683
  Concatenation =   4592961 nanosecond
  Format        =  60114307 nanosecond
  StringBuilder =   2129387 nanosecond

TEST: 10, RUN: 2, Iterations: 19683
  Concatenation =   1850166 nanosecond
  Format        =  35940524 nanosecond
  StringBuilder =   1885544 nanosecond

  ____________________________

TEST: 12, RUN: 1, Iterations: 177147
  Concatenation =  26847286 nanosecond
  Format        = 126332877 nanosecond
  StringBuilder =  17578914 nanosecond

TEST: 12, RUN: 2, Iterations: 177147
  Concatenation =  24405056 nanosecond
  Format        = 129707207 nanosecond
  StringBuilder =  12253840 nanosecond

Aqui está o mesmo teste como acima com a modificação de chamar o toString () método no StringBuilder . Os resultados abaixo demonstram que a abordagem StringBuilder é apenas um pouco mais lento do que concatenação de String usando o + operador.

arquivo: StringTest.java

class StringTest {

  public static void main(String[] args) {

    String formatString = "Hi %s; Hi to you %s";

    long start = System.currentTimeMillis();
    for (int i = 0; i < 1000000; i++) {
        String s = String.format(formatString, i, +i * 2);
    }

    long end = System.currentTimeMillis();
    System.out.println("Format = " + ((end - start)) + " millisecond");

    start = System.currentTimeMillis();

    for (int i = 0; i < 1000000; i++) {
        String s = "Hi " + i + "; Hi to you " + i * 2;
    }

    end = System.currentTimeMillis();

    System.out.println("Concatenation = " + ((end - start)) + " millisecond");

    start = System.currentTimeMillis();

    for (int i = 0; i < 1000000; i++) {
        StringBuilder bldString = new StringBuilder("Hi ");
        bldString.append(i).append("Hi to you ").append(i * 2).toString();
    }

    end = System.currentTimeMillis();

    System.out.println("String Builder = " + ((end - start)) + " millisecond");

  }
}

Shell Comandos: (compilar e executar StringTest 5 vezes)

> javac StringTest.java
> sh -c "for i in \$(seq 1 5); do echo \"Run \${i}\"; java StringTest; done"

Resultados:

Run 1
Format = 1290 millisecond
Concatenation = 115 millisecond
String Builder = 130 millisecond

Run 2
Format = 1265 millisecond
Concatenation = 114 millisecond
String Builder = 126 millisecond

Run 3
Format = 1303 millisecond
Concatenation = 114 millisecond
String Builder = 127 millisecond

Run 4
Format = 1297 millisecond
Concatenation = 114 millisecond
String Builder = 127 millisecond

Run 5
Format = 1270 millisecond
Concatenation = 114 millisecond
String Builder = 126 millisecond

String.format() é mais do que cordas apenas concatenando. Por exemplo, você pode exibir números em um local específico usando String.format().

No entanto, se você não se preocupam com a localização, não há diferença funcional. Talvez aquele é mais rápido do que o outro, mas na maioria dos casos, será insignificante ..

Geralmente, concatenação deve ser preferido ao longo String.format. Este último tem duas desvantagens principais:

  1. Ele não codifica a cadeia a ser construído de forma local.
  2. O processo de construção é codificado em uma string.

Ao ponto 1, quero dizer que não é possível entender o que uma chamada String.format() está fazendo em uma única passagem sequencial. Um deles é forçado a ir e voltar entre a cadeia de formato e os argumentos, enquanto conta a posição dos argumentos. Para concatenations curtas, este não é um grande problema. Nesses casos, no entanto, de concatenação é menos detalhada.

Ao ponto 2, quero dizer que a parte mais importante do processo de construção é codificado no string formato (usando uma conexão DSL). Usando cordas para representar código tem muitas desvantagens. Não é tipo seguro inerentemente, e complica sintaxe-destacando, análise de código, otimização, etc.

É claro que, ao usar ferramentas ou estruturas externas à linguagem Java, novos fatores podem entrar em jogo.

Eu não fiz qualquer referência específicos, mas eu acho que concatenação pode ser mais rápido. String.format () cria uma nova Formatador que, por sua vez, cria um novo StringBuilder (com um tamanho de apenas 16 caracteres). Isso é uma boa quantidade de sobrecarga, especialmente se estiver a formatar uma cadeia mais longa e StringBuilder continua tendo para redimensionar.

No entanto, a concatenação é menos útil e mais difícil de ler. Como sempre, vale a pena fazer uma referência em seu código para ver o que é melhor. As diferenças podem ser insignificante no aplicativo de servidor após o seu pacotes de recursos, locais, etc são carregados na memória e o código é JITted.

Talvez como uma boa prática, seria uma boa idéia para criar o seu próprio Formatter com um StringBuilder de tamanho adequado (appendable) e Locale eo uso que se você tem um monte de formatação para fazer.

Pode haver uma diferença perceptível.

String.format é bastante complexa e usa uma expressão regular por baixo, por isso não torná-lo um hábito de usá-lo em todos os lugares, mas apenas quando você precisar dele.

StringBuilder seria uma ordem de magnitude mais rápido (como alguém aqui já apontado).

Você não pode comparar concatenação de string e String.Format pelo programa acima.

Você pode tentar isso também ser trocando a posição de usar seu String.Format e concatenação em seu bloco de código como o abaixo

public static void main(String[] args) throws Exception {      
  long start = System.currentTimeMillis();

  for( int i=0;i<1000000; i++){
    String s = String.format( "Hi %s; Hi to you %s",i, + i*2);
  }

  long end = System.currentTimeMillis();
  System.out.println("Format = " + ((end - start)) + " millisecond");
  start = System.currentTimeMillis();

  for( int i=0;i<1000000; i++){
    String s = "Hi " + i + "; Hi to you " + i*2;
  }

  end = System.currentTimeMillis();
  System.out.println("Concatenation = " + ((end - start)) + " millisecond") ;
}

Você vai se surpreender ao ver que as obras de formato mais rápido aqui. Isto é porque os objetos intial criadas não pode ser liberado e pode haver um problema com a alocação de memória e, assim, o desempenho.

É preciso um pouco de tempo para se acostumar com String.Format, mas vale a pena na maioria dos casos. No mundo da NRA (nunca repita qualquer coisa) é extremamente útil para manter suas mensagens tokenized (madeireiras ou usuário) em uma biblioteca Constante (eu prefiro o que equivale a uma classe estática) e chamá-los, se necessário com String.Format, independentemente de você estão localizando ou não. Tentando usar como uma biblioteca com um método de concatenação é mais difícil de ler, solucionar problemas, revisar e gerenciar com qualquer qualquer abordagem que requer concatenação. A substituição é uma opção, mas eu duvido que é performance. Depois de anos de uso, o meu maior problema com String.Format é a duração da chamada é inconvenientemente longa quando eu estou passando-lo em outra função (como Msg), mas isso é fácil de se locomover com uma função personalizada para servir como um alias .

Eu acho que podemos ir com MessageFormat.format como deve ser bom em ambos os aspectos de desempenho de legibilidade e também.

Eu usei o mesmo programa que aquele usado pelo Icaro em sua resposta acima e eu reforçada com anexação de código para usar MessageFormat para explicar os números de desempenho.

  public static void main(String[] args) {
    long start = System.currentTimeMillis();
    for (int i = 0; i < 1000000; i++) {
      String s = "Hi " + i + "; Hi to you " + i * 2;
    }
    long end = System.currentTimeMillis();
    System.out.println("Concatenation = " + ((end - start)) + " millisecond");

    start = System.currentTimeMillis();
    for (int i = 0; i < 1000000; i++) {
      String s = String.format("Hi %s; Hi to you %s", i, +i * 2);
    }
    end = System.currentTimeMillis();
    System.out.println("Format = " + ((end - start)) + " millisecond");

    start = System.currentTimeMillis();
    for (int i = 0; i < 1000000; i++) {
      String s = MessageFormat.format("Hi %s; Hi to you %s", i, +i * 2);
    }
    end = System.currentTimeMillis();
    System.out.println("MessageFormat = " + ((end - start)) + " millisecond");
  }

= concatenação 69 milissegundo

Format = 1435 milissegundos

= 200 MessageFormat milissegundo

Atualizações:

De acordo com SonarLint Report, cadeias de formato Printf de estilo deve ser usado corretamente (lula: S3457)

Porque seqüências de formato de estilo printf são interpretados em tempo de execução, em vez de validados pelo compilador, que pode conter erros que resultam nas cordas erradas sendo criado. Esta regra estaticamente valida a correlação de seqüências de formato de estilo printf para os seus argumentos ao chamar o formato (...) métodos de java.util.Formatter, java.lang.String, java.io.PrintStream, MessageFormat e java.io aulas .PrintWriter e do printf (...) métodos de classes java.io.PrintStream ou java.io.PrintWriter.

I substituir o estilo printf com as curvas de menor e maior e eu tenho algo resultados interessantes como abaixo.

A concatenação = 69 milissegundos
Format = 1,107 milissegundo
Formato: Curly-colchetes = 416 milissegundos
MessageFormat = 215 milissegundo
MessageFormat: Curly-colchetes = 2,517 milissegundo

Minha Conclusão:
Como eu destaquei acima, usando String.format com Curly-colchetes deve ser uma boa escolha para obter benefícios de uma boa legibilidade e também o desempenho.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top