2011-11-04 9 views
20

यह एक साक्षात्कार सवाल था। मुझे StringBuffer कार्य को लागू करने के लिए कहा गया था। मैंने साक्षात्कार के बाद कोड देखा। लेकिन मैं समझ नहीं पा रहा हूं कि एक वस्तु के निर्माण के साथ ऑपरेशन कैसे किया जाता है।स्ट्रिंगबफर दो ऑब्जेक्ट्स बनाये बिना एपेंड फ़ंक्शन को कैसे कार्यान्वित कर रहा है?

मैं इस तरह सोच रहा हूं।

String s = "orange"; 
s.append("apple"); 

यहां दो वस्तुएं बनाई गई हैं।

लेकिन

StringBuilder s = new StringBuilder("Orange"); 
s.append("apple"); 

अब यहाँ केवल एक वस्तु बन जाता है।

जावा इस ऑपरेशन को कैसे कर रहा है?

+0

सवाल में कुछ मान्यताओं जो सही नहीं हैं कर रहे हैं। 'नया स्ट्रिंगबिल्डर()' और 'नया स्ट्रिंग()' दो ऑब्जेक्ट बनाता है। –

+3

क्या यह मेरा सवाल था? ;) –

उत्तर

45

पहले वहाँ अपने प्रश्न के साथ एक समस्या है ", स्ट्रिंगबफर/स्ट्रिंगबिल्डर के अंदर कोई ऑब्जेक्ट नहीं बनाया जाएगा यदि हम बफर को ओवरफ़्लो नहीं करते हैं। तो कोड की उन पंक्तियों 2 या 3 वस्तुओं बनाते हैं।

StringBuilder s = new StringBuilder("Orange"); 
s.append("apple"); 

अब यहाँ केवल एक ही वस्तु

बनाई गई है मैं नहीं जानता कि जहां कि, यहाँ आप एक StringBuilder वस्तु, एक "ऑरेंज" स्ट्रिंग, एक "सेब" स्ट्रिंग बनाने मिलता है , कुल 3 ऑब्जेक्ट्स के लिए, या 4 अगर हम स्ट्रिंगबिल्डर बफर ओवरफ्लो करते हैं। (मैं वस्तु निर्माण के रूप में सरणी निर्माण गिनती)।


मैं के रूप में अपने प्रश्न पढ़ें, कैसे StringBuilder एक नई वस्तु (जब बफर बहकर नहीं है) बनाने के बिना संलग्न कर सकते हैं?

आपको StringBuilder पर देखना चाहिए, क्योंकि यह गैर थ्रेड सुरक्षित कार्यान्वयन है।कोड दिलचस्प और पढ़ने के लिए आसान है। मैंने इनलाइन टिप्पणियां जोड़ दी हैं।

आंतरिक संरचना के रूप में वहाँ एक चार सरणी, नहीं एक स्ट्रिंग है। यह शुरुआत में लंबाई 16 के साथ बनाया गया है और क्षमता पार होने पर हर बार बढ़ाई जाएगी। यदि तारों को चार सरणी के भीतर फिट करने के लिए स्ट्रिंग्स हैं, तो नए ऑब्जेक्ट्स बनाने की कोई आवश्यकता नहीं है।

StringBuilder फैली AbstractStringBuilder है, जहां आप निम्नलिखित कोड मिल जाएगा:

/** 
* The count is the number of characters used. 
*/ 
int count; 
:

/** 
* The value is used for character storage. 
*/ 
char value[]; 

के बाद से नहीं सभी सरणी एक निश्चित समय पर उपयोग किया जाएगा, एक और महत्वपूर्ण चर लंबाई है

संलग्न करने के कई अधिभार हैं, लेकिन सबसे दिलचस्प एक निम्नलिखित है:

public AbstractStringBuilder append(String str) { 
    if (str == null) str = "null"; //will literally append "null" in case of null 
    int len = str.length(); //get the string length 
    if (len == 0) return this; //if it's zero, I'm done 
    int newCount = count + len; //tentative new length 
    if (newCount > value.length) //would the new length fit? 
     expandCapacity(newCount); //oops, no, resize my array 
    str.getChars(0, len, value, count); //now it will fit, copy the chars 
    count = newCount; //update the count 
    return this; //return a reference to myself to allow chaining 
} 

String.getChars (पूर्णांक srcBegin, पूर्णांक srcEnd, चार [] डीएसटी, पूर्णांक dstBegin) गंतव्य चरित्र सरणी में इस स्ट्रिंग से प्रतियां अक्षर।

तो, संलग्न विधि काफी सरल है, केवल जादू की खोज करने expandCapacity है छोड़ दिया है, यहाँ यह है:

void expandCapacity(int minimumCapacity) { 
    //get the current length add one and double it 
    int newCapacity = (value.length + 1) * 2; 
    if (newCapacity < 0) { //if we had an integer overflow 
     newCapacity = Integer.MAX_VALUE; //just use the max positive integer 
    } else if (minimumCapacity > newCapacity) { //is it enough? 
     //if doubling wasn't enough, use the actual length computed 
     newCapacity = minimumCapacity; 
    } 
    //copy the old value in the new array 
    value = Arrays.copyOf(value, newCapacity); 
} 

Arrays.copyOf (चार [] मूल, पूर्णांक newLength) प्रतियां निर्दिष्ट सरणी, छंटनी या नल वर्णों के साथ पैडिंग (यदि आवश्यक हो) तो प्रतिलिपि निर्दिष्ट लंबाई है।

हमारे मामले, गद्दी में, हम लंबाई का विस्तार कर रहे के बाद से।

+3

क्या आप समझा सकते हैं क्यों विस्तार क्षमता में, पहला मान। लम्बाई 1 से बढ़ी है, और फिर 2 से गुणा किया गया है? क्या शून्य की संख्या – CyprUS

9

source आपका दोस्त है, ल्यूक!

यहाँ के लिए AbstractStringBuilder

+0

सारस्ट्रिंगबिल्डर स्ट्रिंगबिल्डर –

4

String अपरिवर्तनीय है स्रोत है। एक स्ट्रिंग को जोड़ना केवल एक नई स्ट्रिंग उत्पन्न कर सकता है।

StringBuilder उत्परिवर्तनीय है। StringBuilder में शामिल करना एक इन-प्लेस ऑपरेशन है, जैसे कि ऐरेलिस्ट में जोड़ना।

+0

के मूल वर्ग होने के नाते हाय स्लैक्स, मुझे पता है। मैं जानना चाहता हूं कि स्ट्रिंग बिल्डर उस ऑपरेशन को कैसे कर रहा है। – javaMan

2

स्ट्रिंगबफर जैसे स्ट्रिंगबफर, चार की एक सरणी आवंटित करता है जिसमें यह आपके द्वारा संलग्न तारों की प्रतिलिपि बनाता है। यह केवल नई ऑब्जेक्ट बनाता है जब वर्णों की संख्या सरणी के आकार से अधिक हो जाती है, जिस स्थिति में यह सरणी को पुन: आवंटित करता है और प्रतिलिपि बनाता है।

1

StringBuilder एक char[] में char एस के एक बफर पकड़े और उन्हें एक String को बदलने जब toString कहा जाता है।

String s = "orange"; 
s.append("apple"); 

यहाँ दो वस्तुओं

सही बनाई गई हैं, दो वस्तुओं बनाई गई हैं, स्ट्रिंग "नारंगी" और स्ट्रिंग "सेब:

3

यह संकलन नहीं है।

String S= "orange"; 
S.append("apple"); 

यदि आप ऐसा

final String S= "orange"; 
final S2 = S + "apple"; 

यह किसी भी वस्तुओं के रूप में यह दो स्ट्रिंग शाब्दिक को संकलन समय पर अनुकूलित है नहीं बनाता है।

StringBuilder s = new StringBuilder("Orange"); 
s.append("apple"); 

यह दो वस्तुओं StringBuilder और char[] यह लपेटता पैदा करता है। यदि आप

String s2 = s.toString(); 

यह दो और ऑब्जेक्ट्स बनाता है।

आप

String S= "orange"; 
S2 = S + "apple"; 

करते हैं इस रूप में

String S2 = new StringBuilder("orange").append("apple").toString(); 

जो 2 + 2 = 4 वस्तुओं बनाता है एक ही है।

0

जैसा कि अन्य वर्णित हैं, StringBuffer उत्परिवर्तनीय है और इसे char सरणी का उपयोग करके कार्यान्वित किया जाता है। StringBuffer में संचालन इन-प्लेस ऑपरेशंस हैं।

अधिक जानकारी नीचे दिए गए लिंक http://www.concentric.net/~ttwang/tech/jfastbuf.htm

यह एक char सरणी का उपयोग कर सरल StringBuffer कार्यान्वयन से पता चलता से उपलब्ध हो सकता है।

2
String s = "orange"; 
s.append("apple"); 

यह सही नहीं है क्योंकि संलग्न विधि स्ट्रिंग में उपलब्ध नहीं है:

-1
****String s1="Azad"; ----One object will create in String cons. pool 

System.out.println(s1);--output--Azad 

s1=s1.concat("Raja"); Two object will create 1-Raja,2-AzadRaja and address of AzadRaja Store in reference s1 and cancel ref.of Azad object 

System.out.println(s1); --output AzadRaja**** 
+0

के लिए खाते की वृद्धि की आवश्यकता है आपका उत्तर पढ़ने में बहुत मुश्किल है। क्या यह कोई उपयोगी जानकारी जोड़ता है जो स्वीकार्य उत्तर में पहले से मौजूद नहीं है? –

1

tl; डॉ: सरल शब्दों में, प्रत्येक स्ट्रिंग संयोजन अभिव्यक्ति+ चरित्र का उपयोग कर एक की ओर जाता है नए String ऑब्जेक्ट प्रारंभिक तारों की सामग्री को नए में कॉपी किया जा रहा है। StringBuffer में एक आंतरिक संरचना है जो केवल तभी विस्तारित होती है जब वर्ण आवश्यक होते हैं।

अरे, लेकिन बहुत से लोग + स्ट्रिंग concatenation का उपयोग करते हैं!

अच्छा, हम/उन्हें नहीं करना चाहिए। कि, आकार बदलता है सच है, लेकिन शायद ही कभी अगर एल्गोरिथ्म का आकार बदलने में लागू कुशल है, और केवल एक String वस्तु एक बार बनाई गई है कि toString() -

स्मृति के उपयोग के मामले में, आप वर्ण धारण करने के लिए में StringBuffer में एक सरणी का उपयोग कर रहे प्रत्येक + कॉन्सटेनेशन पर एक नई String ऑब्जेक्ट के निर्माण से कहीं बेहतर है।

समय जटिलता के संदर्भ में, वर्ण नया स्ट्रिंग (O(n) समय जटिलता) है, जो सामान्य रूप में + ऑपरेटर, जिस पर प्रत्येक ऑपरेशन एक नई प्रतिलिपि की ओर जाता है का उपयोग कर स्ट्रिंग संयोजन की तुलना में बेहतर करना होगा है _chars से केवल एक बार कॉपी कर रहे हैं पात्रों की एक नई वस्तु के लिए, O(1 + 2 + .... + n) = O(n^2) संचालन के लिए अग्रणी।

क्या मुझे अपने आप को एक लागू करना चाहिए?

व्यायाम के मामले में यह आपके लिए अच्छा होगा, लेकिन आधुनिक भाषाएं उत्पादन कोड में इसका उपयोग करने के लिए देशी StringBuffer कार्यान्वयन प्रदान करती हैं।

चार आसान चरणों में:

  1. एक MyCustomStringBuilder वर्ग कि आंतरिक रूप से (निजी तौर पर) एक सरणी रखती बनाएं एक निश्चित प्रारंभिक आकार के पात्रों में से (इसे _chars नाम हैं)। यह सरणी स्ट्रिंग वर्णों रखेगी।
  2. एक विस्तार विधि जोड़ें जो _chars के आकार को के आकार में बढ़ाएगी, होल्डिंग स्ट्रिंग वर्ण की लंबाई इसकी लंबाई से अधिक हो जाएगी। (आप व्यावहारिक रूप से कर रहे हैं, ArrayList आंतरिक रूप से एक साधारण संस्करण को कार्यान्वित कर रहा है)।
  3. stringBufferInstance.append(String s) विधि का उपयोग करते समय वर्ण _chars पर जोड़ें, यदि आवश्यक हो तो इसका आकार बढ़ाएं।
  4. अपने toString() विधि कार्यान्वयन में, आप बस बना सकते हैं एक string using the array:

    public String toString() { 
        return new String(_chars); 
    } 
    

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

  • कोई संबंधित समस्या नहीं^_^