어떤 "if"구문이 더 빠릅니까? 문 또는 삼항 연산자?


83

두 가지 유형이 있습니다 if: 고전 - 자바의 문장 if {} else {}과 속기가 : exp ? value1 : value2. 하나가 다른 것보다 빠르거나 같습니까?

성명서:

int x;
if (expression) {
  x = 1;
} else {
  x = 2;
}

삼항 연산자 :

int x = (expression) ? 1 : 2;

34
전혀 차이가 없다고 생각합니다. 단지 구문 일뿐입니다. 컴파일러는 다소 악 (또는 뭔가 다른)이며, 내가 틀렸다하지 않는 한
sinelaw

4
(마이크로) 벤치 마크 했습니까? 결과를 공유하십시오.
BalusC 2011 년

3
둘 다 jit'ed 될 것입니다. 전혀 차이가 없을 것입니다. 그리고 물건을 디 컴파일하는 것을 귀찮게하지 마십시오. HotSpot이하는 첫 번째 일은 javac에 의해 적용된 모든 최적화를 제거하는 것입니다 .
Ivo Wetzel 2011 년

11
속도가 다르면 존재하지 않습니다. 그들은 다른 목적으로 존재합니다. 나는 당신이 진술과 표현의 차이점을 이해한다고 확신합니다. 문은 작업을 수행합니다. 식은 값을 생성합니다. if문에 사용하기위한 것입니다. ?표현식에 사용됩니다.
Mike Dunlavey 2011 년

3
이 질문에 대한 답변은 원래 질문의 의도가 잘못된 경우에도 읽을 가치가 있으므로 +1하십시오.
jball

답변:


106

거기에는 한 가지 유형의 "if"문만 있습니다. 다른 하나는 조건식입니다. 어느 쪽이 더 나은 성능을 낼지에 관해서는 동일한 바이트 코드로 컴파일 할 수 있으며, 동일하게 작동 할 것으로 기대합니다.

때로는 if문이 더 읽기 쉽고 조건 연산자가 더 읽기 쉽습니다. 두 피연산자가 간단하고 부작용이없는 경우 두 가지의 주요 목적은 경우 반면 특히, 나는, 조건 연산자를 사용하는 것이 좋습니다 것 입니다 그들의 부작용, 내가 아마 사용하십시오 if문을.

다음은 샘플 프로그램과 바이트 코드입니다.

public class Test {
    public static void main(String[] args) {
        int x;
        if (args.length > 0) {
            x = 1;
        } else {
            x = 2;
        }
    }

    public static void main2(String[] args) {
        int x = (args.length > 0) ? 1 : 2;
    }
}

다음으로 디 컴파일 된 바이트 코드 javap -c Test:

public class Test extends java.lang.Object {
  public Test();
    Code:
       0: aload_0
       1: invokespecial #1
       4: return

  public static void main(java.lang.String[]
    Code:
       0: aload_0
       1: arraylength
       2: ifle          10
       5: iconst_1
       6: istore_1
       7: goto          12
      10: iconst_2
      11: istore_1
      12: return

  public static void main2(java.lang.String[
    Code:
       0: aload_0
       1: arraylength
       2: ifle          9
       5: iconst_1
       6: goto          10
       9: iconst_2
      10: istore_1
      11: return
}

보시다시피, 여기에서 바이트 코드 에는 약간의 차이 istore_1가 있습니다. 브랜 스 내 에서 발생 하든 그렇지 않든 (이전의 큰 결함이있는 시도와는 달리 :) JITter가 다른 네이티브 코드로 끝났다면 매우 놀랍습니다.


s / 조건문 / 조건부 표현식 /
Laurence Gonsalves 2011 년

1
당신이 두 가지 모두를 의미하지 않았고 정확히 똑같다는 것을 추측 main하고 main2있습니까?
ColinD 2011 년

감동적인. 지금까지 바이트 코드를 컴파일 할 수 있는지 몰랐습니다.
Kyle

2
@Kyle : Java를 컴파일 한 다음 javap로 디 컴파일했습니다.
Jon Skeet 2011 년

1
@Kyle : 맞습니다. 나는 대부분 바이트 코드가 동일 할 것으로 예상했습니다 . 그대로, 거의 동일합니다. :)
Jon Skeet 2011 년

10

두 예제 모두 동일하거나 거의 동일한 바이트 코드로 컴파일되므로 성능에 차이가 없습니다.

실행 속도에 차이가 있었다면 여전히 가장 관용적 인 버전을 사용해야합니다 (단순 조건과 두 개의 간단한 하위 표현식을 기반으로 단일 변수를 할당하는 두 번째 버전, 더 복잡한 작업을 수행하는 첫 번째 버전). 또는 한 줄에 맞지 않는 작업).


8

이것들은 동일합니다. 둘 다 상당히 빠르며 일반적으로 약 10-30 나노초입니다. (사용 패턴에 따라 다름)이 기간이 귀하에게 중요합니까?

가장 분명하다고 생각되는 일을해야합니다.


4

다른 모든 답변에 추가하려면 :

두 번째 표현식은 종종 3 차 / 삼항 연산자 / 문이라고합니다. 표현식을 반환하므로 매우 유용 할 수 있습니다. 때로는 일반적인 짧은 문에 대해 코드를 더 명확하게 만듭니다.


4
실제로 이것의 좋은 예 : Java에서 표현식의 결과를 기반으로 문자열을 최종적으로 만들어야하는 경우 삼항 구문 final String whichTable = (Integer.parseInt (clientId)> 500)? "serverClients": "offlineClients"; 그런 다음 whichTable이 최종이어야하는 곳에서 표현식의 값을 사용할 수 있습니다. 다음은 불법입니다. final String whichTable = ""; if (Integer.parseInt (clientId)> 500) {whichTable = "serverClients"; } else {whichTable = "offlineClients"; }
제임스 Perih

@JamesPerih final필드 의 경우 생성자 블록을 사용하여 값을 설정할 수 있으며 (조건부 연산자가 IMO보다 10 억 배 더 좋아 보이지만) 로컬 변수를 사용하면 나중에 코드 블록에서 처음 사용하기 전에 값을 할당 할 수 있습니다. 삼항이 이점을 제공하는 유일한 경우 는 생성자를 if-else호출 super(...)하거나 this(...)내부에서 호출 할 때 입니다.
Kröw


0

삼항 연산자는 if-else 조건보다 빠릅니다.

public class TerinaryTest {
    public static void main(String[] args)
    {
        int j = 2,i = 0;
        Date d1 = new Date();
        for(long l=1;l<100000000;l++)
            if(i==1) j=1;
                else j=0;
        Date d2 = new Date();
        for(long l=1;l<100000000;l++)
            j=i==1?1:0;
        Date d3 = new Date();
        System.out.println("Time for if-else: " + (d2.getTime()-d1.getTime()));
        System.out.println("Time for ternary: " + (d3.getTime()-d2.getTime()));
    }
}

시험 결과:

트레일 -1 :

if-else 시간 : 63

삼진 시간 : 31

트레일 -2 :

if-else 시간 : 78

삼진 시간 : 47

트레일 -3 :

if-else 시간 : 94

삼진 시간 : 31

트레일 -4 :

if-else 시간 : 78

삼진 시간 : 47


귀하의 예제를 실행할 때 정확히 반대의 결과가 나타 났는데, 이는 결과가 신뢰할 수 없음을 보여줍니다. 불행히도 당신은 마이크로 벤치마킹 트랩에 빠지고 있습니다. 마이크로 벤치 마크를 올바르게 수행하는 것은 악명 높은 일입니다. 몇 가지 예는 여기에서 볼 수 있습니다. stackoverflow.com/questions/2842695/what-is-microbenchmarking
Rogach

귀하의 특정 예제는 최소한 다음 문제로 어려움을 겪습니다 .4 번의 시도로는 충분하지 않으며 항상 동일한 순서로 테스트를 실행하고 (첫 번째 if-else, 두 번째 삼진) 테스트를 실행하기 전에 JVM을 워밍업하지 않습니다.
Rogach
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.