2015-11-29 30 views
5

मैं कोड के नीचे मिला है और मैंने पूछा था जो विकल्प निम्नलिखित पैटर्न हो जाता है:स्ट्रिंग्स

XXXX-xxxx-xxxx-2324

...

कोड नीचे:

public class CCMark { 

    public static String maskCC(String creditCard){ 

     String x = "XXXX-XXXX-XXXX-"; 
     //line 1 
    } 

    public static void main(String[] args) { 
     System.out.println(maskCC("1234-5678-1234-2324")); 
     System.out.println(maskCC("4567-5678-1234-5643")); 
     System.out.println(maskCC("1234-5678-1234-4654")); 
     System.out.println(maskCC("4567-5678-1234-5435")); 
    } 

} 
संभव विकल्प नीचे

कि "लाइन 1" पर डाला जा सकता है:

A) 
    return x + creditCard.substring(15, 19); 

    B) 
    StringBuilder sb = new StringBuilder(x); 
    sb.append(creditCard, 15, 19); 
    return sb.toString(); 

मुझे लगता है कि यहां सबसे अच्छा विकल्प है, क्योंकि ए और बी हमें एक ही आउटपुट प्रदान करते हैं, बी है, क्योंकि यह स्ट्रिंगबिल्डर का उपयोग कर रहा है जिसका अर्थ है कि इसका दृष्टिकोण उत्परिवर्तनीय है, इसलिए यह विकल्प ए

से कम स्मृति का उपयोग करेगा।

क्या मैं गलत हूँ? क्या यह विकल्प हो सकता है कि इस विशेष स्थिति के लिए विकल्प सबसे अच्छा विकल्प है?

+2

इस मामले में, एक कंपाइलर आपके बजाय – Andrew

+0

के बजाय सभी काम करता है, इसलिए यदि संकलक मेरे लिए सभी काम करता है। विकल्प ए सबसे अच्छा तरीका है क्योंकि कोड की कम लाइनों की आवश्यकता है। सही? –

+0

सिवाय इसके कि जावा कंपाइलर बहुत अनुकूलन नहीं करता है ... यह सी ++ नहीं है। संभावना है कि ए काफी अधिक जीसी का कारण बन जाएगा। –

उत्तर

5

विकल्प ए और बी समान हैं, क्योंकि जावा कंपाइलर विकल्प विकल्प बी में परिवर्तित करेगा। आप विधि के बाहर x की घोषणा को स्थानांतरित कर सकते हैं (और इसे final बनाएं)। कुछ की तरह,

static final String x = "XXXX-XXXX-XXXX-"; 
public static String maskCC(final String creditCard) { 
    return x + creditCard.substring(15, 19); 
} 

के खिलाफ पहले, दूसरे की जाँच करने के javap का उपयोग करना। जावा कोड की तरह,

String x = "XXXX-XXXX-XXXX-"; 
String creditCard = "1234-5678-1234-23324"; 
String x2 = x + creditCard.substring(15, 19); 
StringBuilder sb = new StringBuilder(x); 
sb.append(creditCard, 15, 19); 
String x3 = sb.toString(); 

उत्पन्न बाइट-कोड कि तरह लग रहा है (टिप्पणी लाइनों 6-31और32-58)

0: ldc   #16     // String XXXX-XXXX-XXXX- 
2: astore_1 
3: ldc   #18     // String 1234-5678-1234-23324 
5: astore_2 
6: new   #20     // class java/lang/StringBuilder 
9: dup 
10: aload_1 
11: invokestatic #22     // Method java/lang/String.valueOf:(Ljava/lang/Object;)Ljava/lang/String; 
14: invokespecial #28     // Method java/lang/StringBuilder."<init>":(Ljava/lang/String;)V 
17: aload_2 
18: bipush  15 
20: bipush  19 
22: invokevirtual #31     // Method java/lang/String.substring:(II)Ljava/lang/String; 
25: invokevirtual #35     // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder; 
28: invokevirtual #39     // Method java/lang/StringBuilder.toString:()Ljava/lang/String; 
31: astore_3 
32: new   #20     // class java/lang/StringBuilder 
35: dup 
36: aload_1 
37: invokespecial #28     // Method java/lang/StringBuilder."<init>":(Ljava/lang/String;)V 
40: astore  4 
42: aload   4 
44: aload_2 
45: bipush  15 
47: bipush  19 
49: invokevirtual #43     // Method java/lang/StringBuilder.append:(Ljava/lang/CharSequence;II)Ljava/lang/StringBuilder; 
52: pop 
53: aload   4 
55: invokevirtual #39     // Method java/lang/StringBuilder.toString:()Ljava/lang/String; 
58: astore  5 
60: return 
+0

क्या आप कृपया बता सकते हैं कि कंपाइलर ए से बी क्यों परिवर्तित करता है? क्या यह स्वचालित मामला केवल इस विशेष मामले के लिए है? क्या आप मुझे एक संदर्भ लिंक प्रदान कर सकते हैं? –

+1

@ मार्कोपीयर्रेर्नैन्डेज़ बर्गोस [यह उत्तर] (http://stackoverflow.com/a/8725765/2670892) स्ट्रिंगबिल्डर का स्ट्रिंग अभिव्यक्ति में कैसे उपयोग किया जाता है। –

+0

मुझे संदेह है कि यह 'credCard.substring' को 'एपेंड (src, से, to)' में परिवर्तित करेगा, लेकिन मुझे विश्वास है कि यह केवल 'append (creditCard.substring (..)) के समतुल्य कोड उत्पन्न करेगा, जो' * एक अतिरिक्त प्रतिलिपि और ऑब्जेक्ट आवंटन है। जावा 7 के साथ भी बदतर - सबस्ट्रिंग अधिक महंगा हो गया है। –

2

बड़ा फायदा संस्करण की ए, return x + creditCard.substring(15, 19); है कि यह सरल और साफ है और यह 1 से 8 करने के लिए सभी जावा के संस्करणों में काम करता है। मामले कि अपनी संकलित रूप StringBuffer, के लिए एक सरल recompile का उपयोग करता है में जावा 5 या नए यह बजाय StringBuilder का उपयोग कर देगा। जब आप या तो StringBuffer या StringBuilder मैन्युअल रूप से काम करते हैं तो यह लचीलापन खो जाता है।

सटीक संकलित रूप से तय नहीं किया गया है। चूंकि विधि String.substring विधि का अर्थात् जावा भाषा विशिष्टता द्वारा तय नहीं किया गया है, इसलिए आमतौर पर संकलक इसे स्पर्श नहीं करेंगे और इसे सामान्य विधि आमंत्रण के रूप में संकलित नहीं करेंगे। विनिर्देश स्ट्रिंग कॉन्सटेनेशन (+ ऑपरेटर) के लिए StringBuilder का उपयोग करने के लिए कंपाइलर विक्रेताओं को प्रोत्साहित करता है जब भी लाभ होता है और अधिकांश कंपाइलर ऐसा करते हैं, भले ही कोई लाभ न हो। इधर, दोनों, x और substring का परिणाम है, तो एक सरल String.concat सरल होगा, लेकिन सबसे compilers हमेशा StringBuilder उपयोग करते हैं,
return new StringBuilder().append(x).append(creditCard.substring(15, 19)).toString(); के बराबर करने के लिए संस्करण एक संकलन कर रहे हैं String रों।

अपने संस्करण बी के साथ इस विशिष्ट रूप की तुलना करना, हम निष्कर्ष निकाल सकते हैं कि संस्करण बी दो फायदे हैं प्रदर्शन के लिहाज से:

  • new StringBuilder(x) initializes x.length()+16 की क्षमता है जो पूरे ऑपरेशन के लिए पर्याप्त है करने के लिए StringBuilder, जबकि new StringBuilder() की डिफ़ॉल्ट क्षमता, आमतौर पर वेरिएंट ए के लिए उपयोग की जाती है, 16 वर्णों के लिए तय की जाती है, जो हमारे पास 19 वर्णों का परिणाम है, इस प्रकार एक पुनर्वितरण और अंतर्निहित वर्ण सरणी की प्रतिलिपि

  • sb.append(creditCard, 15, 19); इंटरमीडिएट String इन वर्णों का प्रतिनिधित्व करने की आवश्यकता के बिना चार वर्णों की प्रतिलिपि बनायेगा। substring ऑपरेशन के खर्च कार्यान्वयन के आधार पर भिन्न होते हैं, उदा। ओरेकल के कार्यान्वयन में संस्करण 1.7.0_06 के साथ एक महत्वपूर्ण परिवर्तन हुआ; इस संस्करण सबस्ट्रिंग से शुरू करके नया char[] सरणी प्रभावित चरित्र डेटा की एक प्रतिलिपि पकड़े के रूप में यह एक अलग offset और length क्षेत्र

प्रबंधित नहीं करता है लेकिन ध्यान दें की आवश्यकता है कि संस्करण ए और बी केवल के इन सभी मतभेद प्रदर्शन करने के लिए ऑपरेशन के औपचारिक विवरण को प्रभावित करते हैं। वास्तव में क्या होगा, जेवीएम/जेआरई तक है और आमतौर पर हॉटस्पॉट ऑप्टिमाइज़र बहुत सारे स्ट्रिंग से संबंधित ऑपरेशंस जानता है और फ्यूज ऑपरेशंस या एलिइड इंटरमीडिएट स्ट्रिंग प्रस्तुतियों को फ्यूज कर सकता है। इस प्रकार, प्रदर्शन के नतीजे अपेक्षाकृत अप्रत्याशित हैं और subtle changes to the implementation से प्रभावित हो सकते हैं।

यही कारण है कि डेवलपर्स वैरिएंट ए के साथ चिपक सकते हैं, जैसा कि कहा गया है, सरल और अधिक पठनीय, और केवल एक बार प्रोफाइलर की देखभाल करने के बाद ही प्रदर्शन की देखभाल होती है कि एक प्रदर्शन समस्या है जिसे मैन्युअल रूप से Stringbuilder से निपटकर हल किया जा सकता है।

+0

मुझे लगता है कि ए भी सबसे अच्छा विकल्प है। –