कौन सा "यदि" निर्माण तेज है - कथन या टर्नरी ऑपरेटर?


83

ifजावा में दो प्रकार के कथन हैं - क्लासिक: if {} else {}और शॉर्टहैंड exp ? value1 : value2:। क्या एक दूसरे की तुलना में तेज है या वे एक ही हैं?

बयान:

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

टर्नरी ऑपरेटर:

int x = (expression) ? 1 : 2;

34
मुझे लगता है कि वहाँ बिल्कुल कोई अंतर नहीं है। यह सिर्फ वाक्यविन्यास है। जब तक संकलक कुछ बुराई (या कुछ और) हैं और मैं गलत हूं
पापेलॉ

4
क्या आपने (माइक्रो) बेंचमार्क किया था? परिणाम साझा करें।
बालुस

3
दोनों में जिद हो जाएगी। कोई फर्क नहीं पड़ेगा। और सामान को विघटित करने से परेशान न हों। पहली चीज जो हॉटस्पॉट करता है, वह सभी अनुकूलन को बाहर निकालने के लिए है जो जेवैक द्वारा लागू किए गए थे।
इवो ​​वेटजेल

11
वे अलग-अलग गति के लिए मौजूद नहीं हैं। वे विभिन्न उद्देश्यों के लिए मौजूद हैं। मुझे यकीन है कि आप बयानों और अभिव्यक्तियों के बीच अंतर को समझते हैं। कथन क्रिया करते हैं। भाव मूल्य उत्पन्न करते हैं। ifबयानों में उपयोग के लिए है। ?अभिव्यक्ति में उपयोग के लिए है।
माइक डनलवेई

3
+1 इस प्रश्न की प्रतिक्रियाओं को पढ़ने के लायक है, भले ही मूल प्रश्न का इरादा गलत निर्देशित हो।

जवाबों:


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ब्रांज़ के भीतर होता है या नहीं (मेरे पिछले बेहद त्रुटिपूर्ण प्रयास के विपरीत) :) लेकिन मुझे बहुत आश्चर्य होगा अगर जेटर अलग देशी कोड के साथ समाप्त हो गया।


s / सशर्त कथन / सशर्त अभिव्यक्ति /
लारेंस गोंसाल्वेस

1
मुझे लगता है कि आप दोनों के लिए mainऔर main2बिल्कुल समान होने का मतलब नहीं था ?
कॉलिनड

प्रभावशाली। मुझे नहीं पता था कि आप अभी तक बाइट कोड संकलित कर सकते हैं।
काइल

2
@ बाल: मैंने जावा को संकलित किया, फिर जावप से विघटित हुआ।
जॉन स्कीट

1
@ केश: बिल्कुल। मैं ज्यादातर बाइटकोड के समान होने की उम्मीद करता हूं । जैसा कि यह है, यह लगभग समान है :)
जॉन स्कीट

10

आपके दोनों उदाहरण संभवतः समरूप या लगभग समान बायोटेक का संकलन करेंगे, इसलिए प्रदर्शन में कोई अंतर नहीं होना चाहिए।

यदि निष्पादन की गति में अंतर था, तो आपको अभी भी सबसे मुहावरेदार संस्करण का उपयोग करना चाहिए (जो एक साधारण स्थिति और दो सरल उप-अभिव्यक्तियों के आधार पर एकल चर को असाइन करने के लिए दूसरा होगा, और अधिक जटिल ऑपरेशन करने के लिए पहला एक या ऑपरेशन जो एक लाइन पर फिट नहीं होते हैं)।


8

ये वही हैं। वे दोनों काफी तेज़ हैं, आम तौर पर लगभग 10-30 नैनो-सेकंड। (उपयोग पैटर्न के आधार पर) क्या यह समय सीमा आपके लिए महत्वपूर्ण है?

आपको वही करना चाहिए जो आप मानते हैं कि स्पष्ट है।


4

बस अन्य सभी उत्तरों को जोड़ने के लिए:

दूसरी अभिव्यक्ति को अक्सर तृतीयक / टर्नरी ऑपरेटर / स्टेटमेंट कहा जाता है। यह बहुत उपयोगी हो सकता है क्योंकि यह एक अभिव्यक्ति देता है। कभी-कभी यह विशिष्ट छोटे बयानों के लिए कोड को अधिक स्पष्ट बनाता है।


4
व्यवहार में इसका महान उदाहरण: जावा में, अगर मुझे एक अभिव्यक्ति के परिणाम के आधार पर एक स्ट्रिंग फाइनल करना है, तो मैं टर्नेरी सिंटैक्स फाइनल स्ट्रिंग का उपयोग कर सकता हूं जो = (Integer.parseInt (clientId) - 500)? "serverClients": "offlineClients"; फिर मैं उन जगहों पर अभिव्यक्ति के मूल्य का उपयोग कर सकता हूं जहां अंतिम होने की आवश्यकता होती है। निम्नलिखित गैरकानूनी होगा: अंतिम स्ट्रिंग कौन सा = "; if (Integer.parseInt (clientId)> 500) {whoTable = "serverClients"; } और {whoTable = "offlineClients"; }
जेम्स पेरिह

@JamesPerih एक finalक्षेत्र के मामले में , आप एक मान सेट करने के लिए कंस्ट्रक्टर ब्लॉकों का उपयोग कर सकते हैं (हालांकि सशर्त ऑपरेटर एक अरब गुना बेहतर IMO दिखता है), और स्थानीय चर के साथ, आप पहले कोड में बाद में उपयोग करने से पहले एक मूल्य असाइन कर सकते हैं मुझे लगता है कि मुझे लगता है कि केवल एक मामला है जहां एक सहायक को एक निर्माणकर्ता को if-elseकॉल करते समय super(...)या उसके this(...)अंदर एक फायदा मिलेगा ।
21


0

टर्नरी संचालक अगर-और की स्थिति से तेज है।

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:

अगर-और के लिए समय: 63

टर्नरी के लिए समय: 31

ट्रेल-2:

अगर-और के लिए समय: 78

टर्नरी के लिए समय: 47

ट्रेल-3:

अगर-और के लिए समय: 94

टर्नरी के लिए समय: 31

ट्रेल-4:

अगर-और के लिए समय: 78

टर्नरी के लिए समय: 47


आपके उदाहरण को चलाते समय मेरे ठीक विपरीत परिणाम थे, जिससे पता चलता है कि परिणाम अविश्वसनीय हैं। दुर्भाग्य से आप माइक्रोबेनमार्किंग के जाल में गिर रहे हैं - माइक्रोबेनमार्क को सही ढंग से करना बहुत मुश्किल है। कुछ उदाहरणों के लिए आप यहां देख सकते हैं: stackoverflow.com/questions/2842695/what-is-microbenchmarking
Rogach

आपका विशेष उदाहरण कम से कम इन मुद्दों से ग्रस्त है: 4 परीक्षण कहीं भी पर्याप्त नहीं है, आप हमेशा एक ही क्रम में परीक्षण चलाते हैं (पहला अगर-दूसरा, दूसरा टर्नरी), तो आप परीक्षण चलाने से पहले जेवीएम को वार्म-अप नहीं करते हैं, आदि।
रोगाच
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.