Java의 String Concatenation보다 String.format을 사용하는 것이 더 나은 방법입니까? 사용하는 경향이

String.formatJava에서 사용 및 문자열 연결 사이에 인식 가능한 차이가 있습니까?

나는 사용하는 경향이 String.format있지만 때로는 미끄러 져 연결을 사용합니다. 하나가 다른 것보다 낫는지 궁금합니다.

내가 보는 방식 String.format은 문자열을 “포맷”하는 데 더 많은 힘을줍니다. 연결은 실수로 여분의 % s를 넣거나 누락하는 것에 대해 걱정할 필요가 없음을 의미합니다.

String.format 또한 짧습니다.

더 읽기 쉬운 것은 머리가 어떻게 작동하는지에 달려 있습니다.



답변

사용하는 것이 더 좋습니다 String.format(). 주된 이유는 String.format()리소스 파일에서로드 된 텍스트를 사용하여보다 쉽게 ​​지역화 할 수 있지만 각 언어마다 다른 코드를 사용하여 새 실행 파일을 생성하지 않으면 연결을 지역화 할 수 없기 때문입니다.

앱을 지역화 할 수 있도록 계획하는 경우 형식 토큰의 인수 위치를 지정하는 습관도 가져야합니다.

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

그런 다음 현지화 할 수 있으며 다른 순서를 설명하기 위해 실행 파일을 다시 컴파일하지 않고도 이름 및 시간 토큰을 교환 할 수 있습니다. 인수 위치를 사용하면 함수에 두 번 전달하지 않고 동일한 인수를 다시 사용할 수도 있습니다.

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

답변

성능 정보 :

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");
}

타이밍 결과는 다음과 같습니다.

  • 연결 = 265 밀리 초
  • 형식 = 4141 밀리 초

따라서 연결이 String.format보다 훨씬 빠릅니다.


답변

성능에 대한 토론이 있기 때문에 StringBuilder가 포함 된 비교를 추가 할 것이라고 생각했습니다. 실제로 concat보다 빠르며 자연스럽게 String.format 옵션입니다.

이것을 사과 대 사과 비교의 일종으로 만들기 위해 외부가 아닌 루프에서 새로운 StringBuilder를 인스턴스화합니다 (실제로 마지막에 루프 추가를 위해 공간을 다시 할당하는 오버 헤드로 인해 하나의 인스턴스화를 수행하는 것보다 실제로 더 빠릅니다) 하나의 빌더).

    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 정보 [TestMain]-형식 = 1416 밀리 초
  • 2012-01-11 16 : 30 : 46,190 정보 [TestMain]-연결 = 134 밀리 초
  • 2012-01-11 16 : 30 : 46,313 정보 [TestMain]-문자열 작성기 = 117 밀리 초

답변

한 가지 문제 .format는 정적 유형 안전을 잃는다는 것입니다. 형식에 대한 인수가 너무 적을 수 있으며 형식 지정자에 대해 잘못된 유형을 가질 수 있습니다. 둘 다 IllegalFormatException 런타임 에 발생하므로 프로덕션을 중단시키는 로깅 코드가 생길 수 있습니다.

반대로, 인수 +는 컴파일러에서 테스트 할 수 있습니다.

보안 역사( format함수가 모델링 된) 길고 무섭습니다.


답변

더 읽기 쉬운 것은 머리가 어떻게 작동하는지에 달려 있습니다.

거기에 답이 있습니다.

개인적인 취향의 문제입니다.

문자열 연결이 조금 더 빠르다고 생각하지만 무시할 만합니다.


답변

다음은 밀리 초 단위의 여러 샘플 크기를 사용한 테스트입니다.

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

답변

다음 은 StringBuilder 에서 toString () 메서드를 호출하여 수정 한 위와 동일한 테스트 입니다. 아래 결과는 StringBuilder 접근 방식이 + 연산자를 사용하는 String 연결보다 약간 느립니다 .

파일 : 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");

  }
}

셸 명령 : (StringTest를 5 번 컴파일 및 실행)

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

결과 :

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