2013-02-18 12 views
40

this answer में, यह कहता है (इंगित करता है) स्ट्रिंग कंसटेनेशन को स्ट्रिंगबिल्डर ऑपरेशंस में अनुकूलित किया गया है, इसलिए जब मैं अपना कोड लिखता हूं, तो क्या स्रोत में स्ट्रिंगबिल्डर कोड लिखने का कोई कारण है? ध्यान दें कि मेरा उपयोग केस ओपी के प्रश्न से अलग है, क्योंकि मैं सैकड़ों हजारों लाइनों को जोड़ रहा/जोड़ रहा हूं।जावा: स्ट्रिंग बिल्डर बनाम स्ट्रिंगबिल्डर - अनुकूलित, तो मुझे क्या करना चाहिए?

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

+1

यहां अच्छा विश्लेषण है: http://www.javacodegeeks.com/2013/03/java-stringbuilder-myth-debunked.html – marcolopes

उत्तर

105

मुझे लगता है कि StringBuilder बनाम + के उपयोग वास्तव में संदर्भ आप में प्रयोग कर रहे हैं पर निर्भर करता है।

आम तौर पर JDK 1.6 का उपयोग कर और संकलक ऊपर स्वचालित रूप से StringBuilder का उपयोग कर एक साथ तार में शामिल हो जाएगा।

String one = "abc"; 
String two = "xyz"; 
String three = one + two; 

यह संकलन होगा String three के रूप में:

String three = new StringBuilder().append(one).append(two).toString(); 

यह काफी उपयोगी है और हमें कुछ क्रम बचाता है। हालांकि यह प्रक्रिया हमेशा अनुकूल नहीं है। उदाहरण के लिए ले लो:

String out = ""; 
for(int i = 0; i < 10000 ; i++) { 
    out = out + i; 
} 
return out; 

हम बाईटकोड को संकलन और उसके बाद विघटित बाईटकोड उत्पन्न हम की तरह कुछ मिलता है:

String out = ""; 
for(int i = 0; i < 10000; i++) { 
    out = new StringBuilder().append(out).append(i).toString(); 
} 
return out; 

संकलक भीतरी पाश को अनुकूलित किया है लेकिन निश्चित रूप से सबसे अच्छा संभव अनुकूलन नहीं किया है ।हमारे कोड में सुधार करने के लिए हम इस्तेमाल कर सकते हैं:

StringBuilder out = new StringBuilder(); 
for(int i = 0 ; i < 10000; i++) { 
    out.append(i); 
} 
return out.toString(); 

अब इस संकलक उत्पन्न कोड की तुलना में अधिक इष्टतम है, इसलिए वहाँ निश्चित रूप से ऐसे मामलों में जहां कुशल कोड की जरूरत है में StringBuilder/StringBuffer वर्गों का उपयोग कोड लिखने के लिए एक की जरूरत है। मौजूदा कंपाइलर्स लूप में तारों को जोड़ने में बहुत अच्छे नहीं हैं, हालांकि यह भविष्य में बदल सकता है।

आपको यह देखने के लिए ध्यान से देखना होगा कि आपको StringBuilder मैन्युअल रूप से लागू करने की आवश्यकता है और इसका उपयोग करने का प्रयास करें जहां यह आपके कोड की पठनीयता को भी कम नहीं करेगा।

नोट: मैंने जेडीके 1.6 का उपयोग करके कोड संकलित किया, और javap प्रोग्राम का उपयोग करके कोड को डीकंपिल्ड किया, जो बाइट कोड थूकता है। यह समझना काफी आसान है और अक्सर कोड को अनुकूलित करने का प्रयास करते समय देखने के लिए एक उपयोगी संदर्भ है। कंपाइलर आपको दृश्यों के पीछे कोड बदल देता है, इसलिए यह देखना हमेशा दिलचस्प होता है कि यह क्या करता है!

+3

क्या आपका डिकंपिल्ड कोड (लूप के लिए दूसरे में) एक वास्तविक अपघटन का आउटपुट है, या यह आपका अनुमान है? यदि आप इसमें "+" स्ट्रिंग कॉन्सटेनेशन के साथ/lop के लिए एक डीबग डीबग करते हैं, तो आप पाएंगे कि स्ट्रिंगबिल्डर ऑब्जेक्ट प्रत्येक लूप में नहीं बनाया गया है, लेकिन वास्तव में वही पुन: उपयोग किया जाता है। अन्यथा, यदि आप एक भारी वस्तु को प्रतिस्थापित कर रहे हैं (यानी स्ट्रिंगबिल्डर स्ट्रिंग के लिए), तो आप वास्तव में क्या अनुकूलन प्राप्त कर रहे हैं? –

+2

मैं भी @SpencerKormos 'प्रश्न का उत्तर जानना चाहता हूं। क्या संकलक वास्तव में प्रत्येक लूप पुनरावृत्ति के लिए एक नया 'स्ट्रिंगबिल्डर' बनाता है? यह इष्टतम क्यों होगा? – ryvantage

+0

उत्तर को फिर से पढ़ना, और ओपी के प्रश्न में लिंक, टॉम बना रहा था, यह था कि यदि लूप में कॉन्सट ऑपरेशन हो रहा है, तो समग्र कोड ब्लॉक पर कंपाइलर द्वारा कोई अनुकूलन नहीं है (जिसमें इसके लिए शामिल होगा पाश)। उस स्थिति में, आप लूप के अंदर * पहले स्ट्रिंगबिल्डर * घोषित करेंगे, और लूप के अंदर एपेंड() का उपयोग करेंगे, जिससे कॉन्सट ऑपरेशन सबसे अधिक कुशल हो जाएगा (यानी टॉम से अंतिम कोड ब्लॉक)। उम्मीद है कि मुझे समझ में आता है, और मुझे इस पर वापस लाने के लिए धन्यवाद! –

0

मैंने आपके प्रश्न को गलत समझा होगा, लेकिन स्ट्रिंगबिल्डर तेजी से स्ट्रिंग जोड़ते समय तेज है। तो, हां, यदि आप "सैकड़ों हजारों लाइनों" को जोड़ रहे हैं, तो आपको निश्चित रूप से स्ट्रिंगबिल्डर (या स्ट्रिंगबफर का उपयोग करना चाहिए यदि आप एक बहुप्रचारित ऐप चला रहे हैं)।

(टिप्पणी में अधिक पूरी तरह से जवाब)

+1

स्पष्ट रूप से आधुनिक/परिपक्व जावा कंपाइलर्स स्ट्रिंगबिल्डर ऑपरेशन ऑपरेशंस में कॉन्सटेनेशन ऑपरेशंस को परिवर्तित करने के लिए पर्याप्त स्मार्ट हैं, तो कोडिंग में स्ट्रिंगबिल्डर का उपयोग करने का क्या मतलब है जब यह कम पठनीय हो, और जब स्ट्रिंग कॉन्सैट स्ट्रिंगबिल्डर ऑपरेशंस में परिवर्तित हो जाते हैं? – Soyuz

+2

ओह अब मैं तुम्हारा बिंदु देखता हूं, दोस्त। हां, आप सही हैं: कंपाइलर आपके कोड को अनुकूलित करने का मौका पहचान लेगा और स्ट्रिंगबिल्डर द्वारा नियमित रूप से एक नियमित String.concat को प्रतिस्थापित करेगा - लेकिन हमेशा नहीं। आप कंपाइलर पर भरोसा नहीं कर सकते हैं। यदि कोड जटिल है, तो संकलक अनुकूलन के अवसर को अच्छी तरह याद कर सकता है। अगर मैं आप थे, तो मैं ऑप्टिमाइज़ेशन सुनिश्चित करने के लिए अपना कोड थोड़ा कम पठनीय बनाना चुनूंगा। – cldjr

2

यह मामला पर निर्भर करता है, लेकिन StringBuilder थोड़ा तेजी से माना जाता है। यदि आप एक लूप के अंदर concatenation कर रहे हैं तो मैं सुझाव देता हूं कि आप स्ट्रिंगबिल्डर का उपयोग करें।

वैसे भी, मैं आपको सलाह देता हूं कि आप अपने कोड को प्रोफाइल और बेंचमार्क करें (यदि आप इतने बड़े पैमाने पर काम कर रहे हैं)।

हालांकि सावधान रहें: स्ट्रिंगबिल्डर के उदाहरण उत्परिवर्तनीय हैं और धागे के बीच साझा नहीं किए जाने चाहिए (जब तक कि आप वास्तव में नहीं जानते कि आप क्या कर रहे हैं।) स्ट्रिंग के विपरीत जो अपरिवर्तनीय हैं।

+0

प्रश्न को दोबारा दोहराएं। मैंने जो कहा है, उसके बारे में मुझे पता है, मेरा मतलब है, मुझे वास्तव में क्या लिखना चाहिए? – Soyuz

+0

बैक अप लेने के लिए वास्तव में कुछ प्रकार का सबूत या स्रोत होना चाहिए "स्ट्रिंगबिल्डर को थोड़ा तेज़ माना जाता है"। मुझे लगता है कि यह सिंक्रनाइज़ेशन ओवरहेड की कमी के कारण है लेकिन अभी भी - स्रोत अच्छा होगा। –

3

आपके प्रश्न में मुख्य वाक्यांश "माना जाता है धीमा" है। आपको यह पहचानने की ज़रूरत है कि यह वास्तव में एक बाधा है, और फिर देखें कि कौन सा तेज़ है।

यदि आप इस कोड को लिखने वाले हैं, लेकिन अभी तक इसे नहीं लिखा है, तो जो कुछ भी स्पष्ट है उसे लिखें और फिर यदि आवश्यक हो तो यह एक बाधा है या नहीं।

हालांकि कोड का उपयोग करने के लिए यह समझ में आता है कि आप अधिक तेज़ी से समझने के लिए समझते हैं, अगर दोनों समान रूप से पठनीय हैं, तो वास्तव में यह पता लगाने के लिए समय लेना कि जब आपकी आवश्यकता नहीं होती है तो समय की बर्बादी होती है। निष्पादन के ऊपर पठनीयता जब तक प्रदर्शन अस्वीकार्य नहीं है।

+0

दरअसल, कोड (दोनों) कोड को दोबारा लिखने के बाद, पठनीयता में थोड़ा अंतर होता है क्योंकि यह कक्षा घोषणाओं को बदल रहा है और कॉन्सैट() को जोड़ने के लिए() को बदल रहा है। मुझे लगता है कि मैं प्रदर्शन सुनिश्चित करने के लिए स्ट्रिंगबिल्डर के साथ रहूंगा। – Soyuz

संबंधित मुद्दे