लूप के बाद एक स्ट्रिंग बफर / बिल्डर को साफ़ करना


122

आप लूप के बाद जावा में स्ट्रिंग बफर को कैसे साफ़ करते हैं ताकि अगले पुनरावृत्ति एक स्पष्ट स्ट्रिंग बफर का उपयोग करे?


2
एक और सवाल: आप लूप के केवल एक पुनरावृत्ति के लिए एसबी का उपयोग क्यों करते हैं? क्या एक और आंतरिक पुनरावृत्ति है? SB योग्य नहीं है यदि आप बस A + B + C + D करना चाहते हैं (Java compiler आंतरिक रूप से SB का उपयोग करेगा)। यह मदद करता है अगर आप सशर्त रूप से तारों के हिस्सों को जोड़ना चाहते हैं, लेकिन अन्यथा ... बस "+" का उपयोग करें।
हेलिओस

जवाबों:


135

एक विकल्प इस प्रकार है:

StringBuffer sb = new StringBuffer();
for (int n = 0; n < 10; n++) {
   sb.append("a");

   // This will clear the buffer
   sb.delete(0, sb.length());
}

एक अन्य विकल्प (बिट क्लीनर) सेटलग्रेन (इंट लेन) का उपयोग करता है :

sb.setLength(0);

अधिक जानकारी के लिए Javadoc देखें :


15
कुछ कम रगड़ने से लूप के अंदर स्ट्रिंगरबफ़र की घोषणा हो जाएगी।
मार्क इलियट

11
आह, मुझे लगता है कि sb.setLength (0); यह लूप के अंदर घोषित करने की तुलना में क्लीनर और अधिक कुशल है। आपका समाधान StringBuffer का उपयोग करने के प्रदर्शन लाभ के खिलाफ जाता है ...
जॉन

6
मुझे लगता है कि प्रदर्शन लाभ स्ट्रिंग उत्परिवर्तन से आता है, तात्कालिकता को बचाने से नहीं। यहाँ 1e8 पुनरावृत्तियों का एक त्वरित परीक्षण है: लूप के अंदर (2.97s): ideone.com/uyyTL14w , लूप के बाहर (2.87): ideone.com/F9lgsIxh
मार्क इलियट

6
प्रदर्शन की बात करना: जब तक आपका कोड बहु-थ्रेडेड परिदृश्य में एक्सेस नहीं किया जाता है, आपको StringBuer के बजाय StringBuilder का उपयोग करना चाहिए - javadoc देखें: "जहां संभव हो, यह अनुशंसा की जाती है कि StringBuffer को प्राथमिकता में इस वर्ग का उपयोग किया जाए क्योंकि यह तेज होगा सबसे अधिक कार्यान्वयन "।
रहल लूथी

4
बाहर एसबी बनाने का एकमात्र लाभ इसके आंतरिक (संभावित लंबे) चार [] को नहीं खो रहा है। यदि पहले पुनरावृत्ति में यह काफी बढ़ गया है, तो दूसरे लूप को किसी भी चार [] को आकार देने की आवश्यकता नहीं होगी। लेकिन लाभ प्राप्त करने के लिए "स्पष्ट विधि" को आंतरिक सरणी के आकार को संरक्षित करना होगा। setLength करता है, लेकिन यह भी SB में उपयोग नहीं किए गए सभी वर्णों को \ u0000 पर सेट करता है, इसलिए यह कम प्रदर्शन है कि बस एक नई एसबी एक अच्छी प्रारंभिक क्षमता के साथ बना रहा है। लूप के अंदर घोषणा करना बेहतर है।
हेलिओस

48

पुन: उपयोग करने का सबसे आसान तरीका StringBufferविधि का उपयोग करना हैsetLength()

public void setLength(int newLength)

आपके पास मामला हो सकता है

StringBuffer sb = new StringBuffer("HelloWorld");
// after many iterations and manipulations
sb.setLength(0);
// reuse sb

2
@Mahmoud, कोड उदाहरण में इसके setLengthबजाय पढ़ना चाहिए setlength
ओनाबाई 15

जब मैं setLength कोड स्रोत देखता हूं, तो यह कैसे काम कर रहा है ( gist.github.com/ebuildy/e91ac6af2ff8a6b1821d18abf2f8c9e1 ) यहां गिनती हमेशा newLength (0) से अधिक होगी?
थॉमस डेकाक्स

20

आपके पास दो विकल्प हैं:

या तो उपयोग करें:

sb.setLength(0);  // It will just discard the previous data, which will be garbage collected later.  

या उपयोग करें:

sb.delete(0, sb.length());  // A bit slower as it is used to delete sub sequence.  

ध्यान दें

लूप के भीतर वस्तुओं की घोषणा करने से बचें StringBufferया StringBuilderफिर यह प्रत्येक पुनरावृत्ति के साथ नई वस्तुओं का निर्माण करेगा। वस्तुओं के निर्माण के लिए सिस्टम संसाधन, स्थान की आवश्यकता होती है और इसमें समय भी लगता है। इसलिए लंबे समय के लिए, यदि संभव हो तो उन्हें लूप के भीतर घोषित करने से बचें।



5

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


2
यदि आपके पास इस तरह के प्रदर्शन अंतर का कोई सबूत है, तो कृपया इसे साझा करें। (मुझे यह
जानकर

1
यह सर्वविदित है कि आवंटन (जावा में नया कीवर्ड) एक ही वस्तु के कुछ क्षेत्रों को बदलने की तुलना में अधिक महंगा है। "ज्यादातर" के लिए, जिसे आप अत्यधिक के साथ दे सकते हैं, 1.5 मिलियन से अधिक एंड्रॉइड डिवाइसेस हैं, सभी जावा का उपयोग कर रहे हैं।
लुई सीएडी

1
मैं मानता हूं कि कुछ मामलों में, कोड पठनीयता प्रदर्शन से अधिक महत्वपूर्ण है, लेकिन इस मामले में, यह कोड की केवल एक पंक्ति है! और आप एक बेंचमार्क चला सकते हैं जो आपको यह साबित करेगा कि आवंटन और ऑब्जेक्ट निर्माण, प्लस कचरा एकत्र करना बिल्कुल भी नहीं करने की तुलना में अधिक महंगा है। जैसा कि हम एक पाश में हैं, यह प्रासंगिक से अधिक है।
लुई कैड

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

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

5
public void clear(StringBuilder s) {
    s.setLength(0);
}

उपयोग:

StringBuilder v = new StringBuilder();
clear(v);

पठनीयता के लिए, मुझे लगता है कि यह सबसे अच्छा समाधान है।


2

वहां पहले से ही अच्छा जवाब। बस स्ट्रिंग बेंचर के लिए एक बेंचमार्क परिणाम जोड़ें और स्ट्रिंगबल्ड प्रदर्शन अंतर लूप में नए उदाहरण का उपयोग करें या लूप में सेटलिफ्ट (0) का उपयोग करें।

सारांश है: एक बड़े लूप में

  • StringBuilder, StringBuffer की तुलना में बहुत तेज़ है
  • लूप में नया StringBuilder उदाहरण बनाएँ setLength (0) के साथ कोई अंतर नहीं है। (setLength (0) का बहुत ही कम लाभ है जो नई मिसाल पैदा करता है।)
  • StringBuffer पाश में नया उदाहरण बनाकर StringBuilder की तुलना में धीमा है
  • StringBuffer का setLength (0) लूप में नया उदाहरण बनाने की तुलना में बेहद धीमी है।

बहुत ही सरल बेंचमार्क (मैंने कोड को मैन्युअल रूप से बदल दिया है और अलग-अलग परीक्षण करता है):

public class StringBuilderSpeed {
public static final char ch[] = new char[]{'a','b','c','d','e','f','g','h','i'};

public static void main(String a[]){
    int loopTime = 99999999;
    long startTime = System.currentTimeMillis();
    StringBuilder sb = new StringBuilder();
    for(int i = 0 ; i < loopTime; i++){
        for(char c : ch){
            sb.append(c);
        }
        sb.setLength(0);
    }
    long endTime = System.currentTimeMillis();
    System.out.println("Time cost: " + (endTime - startTime));
}

}

लूप में न्यू स्ट्रिंगबर्स्ट उदाहरण: समय लागत: 3693, 3862, 3624, 3742

StringBuilder सेट गति: समय लागत: 3465, 3421, 3557, 3408

लूप में नया स्ट्रिंगर उदाहरण: समय लागत: 8327, 8324, 8284

स्ट्रिंगर बफ़र सेट लैंथ टाइम लागत: 22878, 23017, 22894

फिर से StringBuilder setLength सुनिश्चित करने के लिए नहीं कि मेरा लैपटॉप StringBuffer setLength के लिए इतने लंबे समय तक उपयोग करने के लिए कुछ मुद्दा मिला: समय लागत: 3448


0
StringBuffer sb = new SringBuffer();
// do something wiht it
sb = new StringBuffer();

मुझे लगता है कि यह कोड तेज है।


3
इसमें प्रदर्शन के मुद्दे होंगे। यह प्रत्येक पुनरावृत्ति के बाद एक नई वस्तु बनाता है
आदित्य सिंह

@ आदित्यसिंह यह पूरी तरह से उचित दृष्टिकोण है। सबूत के बिना प्रदर्शन की समस्याओं को न मानें।
shmosel

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