सर्वोत्तम अभ्यास / प्रदर्शन: StringBuilder.append को String.concat के साथ मिलाना


86

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

StringBuilder sb = new StringBuilder("AAAAAAAAAAAAA")
    .append(B_String).append("CCCCCCCCCCC").append(D_String)
    .append("EEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE")
    .append("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF");

क्या ऐसा करने का तरीका है? से इस पोस्ट , मैंने देखा है कि +तार पर ऑपरेटर, StringBuilder का एक नया उदाहरण बनाता है ऑपरेंड संयोजित करता है, और एक स्ट्रिंग रूपांतरण, जो सिर्फ बुला तुलना में बहुत अधिक काम की तरह लगता है देता है .append(); तो अगर यह सच है, तो यह सवाल से बाहर है। लेकिन इससे क्या String.concat()? क्या .append()हर कॉन्सेप्ट का इस्तेमाल करना उचित है ? या बस चर के लिए, और शाब्दिक के साथ संलग्न करने के लिए ठीक है .concat()?

StringBuilder sb = new StringBuilder("AAAAAAAAAAAAA")
    .append(B_String.concat("CCCCCCCCCCC")).append(D_String
    .concat("EEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE")
    .concat("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF"));

इन स्थितियों के बारे में जाने के लिए सर्वोत्तम प्रथाओं और प्रदर्शन के सामान्य नियम क्या हैं? क्या मेरी धारणा सही है +और इसका वास्तव में उपयोग नहीं किया जाना चाहिए?


मुझे लगता है कि मूल रूप से आपको मिल गया है। राय में भिन्नता है कि क्या स्ट्रिंग + "वास्तव में सिर्फ उपयोग नहीं किया जाना चाहिए"। मुद्दा यह है कि आप परिणामों को समझते हैं
ControlAltDel

जवाबों:


184

+ ऑपरेटर

String s = s1 + s2

जिन दृश्यों के पीछे इसका अनुवाद किया गया है:

String s = new StringBuilder(s1).append(s2).toString();

कल्पना करें कि अगर आपके s1 + s2यहाँ यह कितना अतिरिक्त काम करता है:

stringBuilder.append(s1 + s2)

के बजाय:

stringBuilder.append(s1).append(s2)

के साथ कई तार +

ध्यान दें कि:

String s = s1 + s2 + s3 + ... +sN

इसका अनुवाद है:

String s = new StringBuilder(s1).append(s2).append(s3)...apend(sN).toString();

concat()

String s = s1.concat(s2);

Stringऐसा char[]एरे बनाता है जो दोनों को फिट कर सकता है s1और s2। इस नए सरणी में प्रतियां s1और s2सामग्री। दरअसल इसके लिए +ऑपरेटर की जरूरत होती है।

StringBuilder.append()

एक आंतरिक char[]सरणी को बनाए रखता है जो जरूरत पड़ने पर बढ़ती है। char[]यदि आंतरिक पर्याप्त रूप से बड़ा है तो कोई अतिरिक्त नहीं बनाया जाता है।

stringBuilder.append(s1.concat(s2))

यह भी खराब प्रदर्शन कर रहा है क्योंकि s1.concat(s2)एक अतिरिक्त char[]सरणी और प्रतियां बनाता है s1और s2यह सिर्फ उस नई सरणी सामग्री को आंतरिक में कॉपी करने के लिए StringBuilder char[]

कहा जा रहा है कि आपको append()हर समय उपयोग करना चाहिए और कच्चे तारों को जोड़ना चाहिए (आपका पहला कोड स्निपेट सही है)।


आपकी मदद के लिए धन्यवाद, और गहराई से स्पष्टीकरण; मुझे वास्तव में यही चाहिए था।
निक रोलैंडो

12
हालांकि संकलक के नए संस्करण स्वचालित रूप से स्ट्रिंग ऑपरेटर के लिए + ऑपरेटर का अनुकूलन करते हैं, यह जरूरी नहीं है कि यह मान लेना अच्छी बात है कि पुराने संस्करण नहीं होंगे। एक बहुत ही महत्वपूर्ण विषय है जिसे इस पूरी चर्चा में नजरअंदाज किया जा रहा है जो वास्तव में स्ट्रींगबुलस्ट के लिए मुख्य उद्देश्यों में से एक है जो स्ट्रिंग पूल है। एक स्ट्रिंग बिल्डर का उपयोग करना सब कुछ एक चार के रूप में रखता है] और एक मध्यवर्ती स्ट्रिंग नहीं बनाता है जैसे कि + ऑपरेटर संकलक अनुकूलन से पहले किया था (केवल एक कॉनैट करने के लिए उपयोग किया जाता है)। कॉनैट का उपयोग करने से एक मध्यवर्ती स्ट्रिंग ऑब्जेक्ट बन जाता है जो कि कैश किया जाता है लेकिन उपयोग नहीं किया जाता है।
LINEMAN78

इसलिए अगर मैं कई अलग-अलग तारों पर एक-बार बयान (एक विधि के बजाय एक से अधिक कथन नहीं) कर रहा हूं । यह एक समय के लिए +एक बनाने के बजाय स्ट्रिंग वस्तुओं पर उपयोग करना ठीक होगा StringBuilder, क्योंकि यह मूल रूप से एक ही काम करेगा?
निक रोलैंडो

1
और अगर मैं केवल एक चरित्र को संक्षिप्त करना चाहता हूं, तो क्या .append ("\ n") के बजाय .append ('\ n') का उपयोग करना बेहतर है? जैसा कि एक चरित्र एक आदिम प्रकार है, और एक स्ट्रिंग एक वस्तु है?
vrwim

3
प्रभावी जावा 2-एनडी संस्करण : एन को समतल करने के लिए बार-बार स्ट्रिंग संघनन ऑपरेटर का उपयोग करने के लिए एन में द्विघात समय की आवश्यकता होती है। तो क्या यह अभी भी प्रासंगिक है?
gkiko

16

संकलनकर्ता + संघनन का अनुकूलन करता है।

इसलिए

int a = 1;
String s = "Hello " + a;

में तब्दील हो गया है

new StringBuilder().append("Hello ").append(1).toString();

यहां एक उत्कृष्ट विषय यह बताते हुए कि आपको + ऑपरेटर का उपयोग क्यों करना चाहिए।


3
कंपाइलर वास्तव में String s = "Hello World";आप के बाद से शाब्दिक उपयोग करते हैं कि में अनुकूलन होगा ।
कोलिनड डीपी

@ColinD: +1। बस मेरे स्निपेट को संशोधित किया।

3

अनुकूलन संकलक द्वारा स्वचालित रूप से किया जाता है।

Java2 संकलक स्वचालित रूप से निम्नलिखित को परिवर्तित करेगा:

String s = s1 + s2; 

सेवा

String s = (new StringBuffer()).append(s1).append(s2).toString();

ओरैकल्स वेबसाइट पर जावा बेस्ट प्रैक्टिस से सीधे लिया गया।


2

आपको हमेशा उपयोग करना चाहिए append

concatएक नया स्ट्रिंग बनाएं ताकि +मुझे लगता है कि यह बहुत सुंदर है।

यदि आप concatया +2 अंतिम स्ट्रिंग के साथ उपयोग करते हैं तो JVM अनुकूलन कर सकता है इसलिए यह इस मामले में एपेंड करने जैसा ही है।


1

यदि आप वास्तव में दो स्ट्रिंग्स का उपयोग करते हैं, तो String.concat का उपयोग करते हैं (एक नया स्ट्रिंग बनाता है, जिसमें एक नया चार-सरणी बनाया जाता है जो स्ट्रिंग्स दोनों को फिट करता है और दोनों स्ट्रिंग्स के चार्ट को इसमें सम्मिलित करता है)।

यदि आप एकाधिक (दो से अधिक) स्ट्रिंग्स को एक पंक्ति में समेटते हैं, तो + या StringBuilder.append का उपयोग करें, इससे कोई फर्क नहीं पड़ता, क्योंकि कंपाइलर StringBuilder.append में परिवर्तित हो जाता है। यह कई स्ट्रिंग्स के लिए अच्छा है क्योंकि यह एक चार सरणी रखता है जो आवश्यकतानुसार बढ़ता है।

यदि आप एक से अधिक स्ट्रिंग्स को एक से अधिक स्ट्रिंग्स बनाते हैं तो एक स्ट्रिंगबर्ल बनाएं और एपेंड-मेथड का उपयोग करें। अंत में जब आप स्ट्रिंग को StringBuilder का उपयोग करने के लिए किया जाता है तो इसका उपयोग .toString () - एक स्ट्रिंग बनाने के लिए विधि है। कई लाइनों में समाप्‍त करने के लिए यह दूसरी विधि की तुलना में तेज है, क्‍योंकि दूसरी विधि से प्रत्येक लाइन पर एक नया स्ट्रिंगबर्ब्‍ट बनेगा, स्ट्रिंग्स को जोड़ेंगे और फिर स्ट्रिंग में वापस लाएंगे, जबकि तीसरी विधि केवल पूरी चीज के लिए एक स्ट्रिंगबर्ल का उपयोग करती है।


0

उपयोग +ऑपरेटर सबसे अच्छा अभ्यास है, यह सरल और पठनीय भी है।

जावा लैंग्वेज स्ट्रिंग कॉन्फिनेशन ऑपरेटर (+) के लिए, और अन्य ऑब्जेक्ट्स को स्ट्रिंग्स में बदलने के लिए विशेष सहायता प्रदान करता है। स्ट्रिंग संघात StringBuilder (या StringBuffer) वर्ग और उसके परिशिष्ट विधि के माध्यम से कार्यान्वित किया जाता है।

आधिकारिक दस्तावेज: https://docs.oracle.com/javase/8/docs/api/java/lang/Stax.html


0

बाइट कोड स्तर में अलग नहीं है और हम वहां पुतलों से समझौता नहीं कर रहे हैं। बाइट कोड स्तर को निष्पादित करने के मामले में, इसे नॉन-इनलाइन ऑपरेटर ओवरलोडिंग पद्धति से गुजरना होगा + के लिए एपेंड को कॉल करके। फिर असेंबली लैंग्वेज लेवल में (Java C में लिखा जाता है और C असेंबली के समान असेंबली बनाता है। स्टैक में स्टोर + मेथड कॉल के लिए अतिरिक्त रजिस्टर कॉल होगा और अतिरिक्त पुश होगा। (वास्तव में, क्रॉस-कंपाइलर + ऑपरेटर को ऑप्टिमाइज़ कर सकता है। कॉल करें, उस स्थिति में इसे प्रभावकारिता से कोई फर्क नहीं पड़ता है।)

पठनीयता बढ़ाने के लिए एक तरीका होना एक अच्छा अभ्यास है। :)


0

मैं व्यक्तिगत रूप से Strings.format(), एक लाइन स्ट्रिंग फॉर्मेटर को पढ़ने के लिए सरल आसान पसंद करता हूं ।

String b = "B value";
String d = "D value";
String fullString = String.format("A %s C %s E F", b, d);
// Output: A B value C D value E F

0

सभी उत्तर बहुत अच्छे और व्याख्यात्मक हैं। लेकिन मुझे लगा कि अन्य स्ट्रिंग कॉन्सेप्टन तकनीकों के आसपास की खोज भी मदद करेगी जैसे - अमरूद जॉइनर, स्ट्रीम्स, स्ट्रिंग.फॉर्मर इत्यादि।

प्रत्येक संघटन तकनीक जावा-स्ट्रिंग-संघनन के प्रदर्शन के बारे में पूरी जानकारी के लिए, जो कि सबसे अच्छा है

संक्षेप में, संघटन प्रदर्शन नहीं के साथ बदलता रहता है। तार करने के लिए। उदाहरण के लिए - 1-10 तारों को समतल करने के लिए, ये तकनीकें सबसे अच्छा काम करती हैं - स्ट्रिंगबर्लस्ट, स्ट्रिंगरबफ़र और प्लस ऑपरेटर। और स्ट्रिंग्स को 100 के दशक तक पहुंचाने के लिए - अमरूद जॉइनर, अपाचे के स्ट्रिंग्स यूटिल्स लाइब्रेरी भी बढ़िया काम करते हैं।

कृपया उपरोक्त ब्लॉग के माध्यम से जाना। यह वास्तव में प्रदर्शन दक्षता को बहुत अच्छी तरह से समझाता है।

धन्यवाद।

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.