जवाबों:
उत्परिवर्तन अंतर:
String
है अपरिवर्तनीय है, अगर आप उनके मूल्यों को बदलने के लिए प्रयास करते हैं, किसी अन्य वस्तु बनाया जाता है, जबकि StringBuffer
और StringBuilder
कर रहे हैं परिवर्तनशील है ताकि वे अपने मूल्यों को बदल सकते हैं।
धागा-सुरक्षा अंतर:
के बीच का अंतर StringBuffer
और StringBuilder
वह यह है कि StringBuffer
धागे की सुरक्षित है। इसलिए जब एप्लिकेशन को केवल एक ही धागे में चलाने की आवश्यकता होती है तो इसका उपयोग करना बेहतर होता है StringBuilder
। StringBuilder
की तुलना में अधिक कुशल है StringBuffer
।
हालात:
String
ऑब्जेक्ट अपरिवर्तनीय है।StringBuilder
यह काफी अच्छा है।StringBuffer
क्योंकि StringBuffer
तुल्यकालिक है ताकि आप धागे की सुरक्षा की है।Strings
जब हम मूल्य में परिवर्तन करते हैं तो दूसरी वस्तु बनाई जाती है। क्या पुरानी वस्तु संदर्भ को शून्य कर दिया गया है ताकि यह कचरा एकत्र किया जा सके GC
या यह कचरा एकत्र किया गया है?
String
के साथ StringBuilder
?
String
करते हैं जब एक अपरिवर्तनीय संरचना उपयुक्त होती है; String
सीपीयू समय या मेमोरी में एक अस्वीकार्य प्रदर्शन दंड प्राप्त कर सकता है, जिससे एक नया वर्ण अनुक्रम प्राप्त हो सकता है (सब्सट्रिंग प्राप्त करना सीपीयू कुशल है क्योंकि डेटा की प्रतिलिपि नहीं बनाई गई है, लेकिन इसका मतलब है कि संभवतः बड़ी मात्रा में डेटा आवंटित किया जा सकता है)।StringBuilder
तब करते हैं जब आपको एक परिवर्तनशील चरित्र अनुक्रम बनाने की आवश्यकता होती है, आमतौर पर एक साथ कई चरित्र दृश्यों को समेटने के लिए।StringBuffer
उन्हीं परिस्थितियों में उपयोग करते हैं StringBuilder
, जिनका आप उपयोग करते हैं , लेकिन जब अंतर्निहित स्ट्रिंग में परिवर्तन सिंक्रनाइज़ किए जाने चाहिए (क्योंकि कई धागे स्ट्रिंग बफर को पढ़ / संशोधित कर रहे हैं)।एक उदाहरण यहाँ देखें ।
मूल बातें:
String
एक अपरिवर्तनीय वर्ग है, इसे बदला नहीं जा सकता।
StringBuilder
एक उत्परिवर्तित वर्ग है जिसे अक्षरों से जोड़ा जा सकता है, वर्णों को प्रतिस्थापित या हटा दिया जाता है और अंततः इसे एक String
StringBuffer
मूल सिंक्रनाइज़ संस्करण में बदल दिया जाता हैStringBuilder
आपको StringBuilder
उन सभी मामलों में प्राथमिकता देनी चाहिए जहां आपके पास केवल एक ही धागा है जो आपकी वस्तु तक पहुंच रहा है।
विवरण:
यह भी ध्यान दें कि StringBuilder/Buffers
जादू नहीं है, वे केवल एक ऐरे का उपयोग एक बैकिंग ऑब्जेक्ट के रूप में करते हैं और एरे को फिर से आवंटित किया जाता है जब कभी भी यह पूर्ण हो जाता है। सुनिश्चित करें और अपनी StringBuilder/Buffer
वस्तुओं को मूल रूप से पर्याप्त रूप से बनाएं जहां उन्हें हर बार .append()
कॉल करने के लिए लगातार फिर से आकार नहीं देना पड़ता है ।
पुन: आकार देने से बहुत पतित हो सकते हैं। यह मूल रूप से बैकिंग एरे को अपने वर्तमान आकार से 2 गुना अधिक आकार देता है, हर बार इसे विस्तारित करने की आवश्यकता होती है। इसका परिणाम यह हो सकता है कि बड़ी मात्रा में रैम आवंटित किया जाता है और तब उपयोग नहीं किया जाता है जब StringBuilder/Buffer
कक्षाएं बड़ी होने लगती हैं।
जावा में पर्दे के पीछे String x = "A" + "B";
का उपयोग किया StringBuilder
जाता है। तो सरल मामलों के लिए अपनी खुद की घोषणा का कोई लाभ नहीं है। लेकिन अगर आप ऐसी String
वस्तुओं का निर्माण कर रहे हैं जो बड़ी हैं, तो 4k से कम कहें, तो घोषणा StringBuilder sb = StringBuilder(4096);
करना , कंफर्टेशन की तुलना में बहुत अधिक कुशल है या डिफ़ॉल्ट कंस्ट्रक्टर का उपयोग करना है जो केवल 16 अक्षर है। यदि आपका String
10k से कम होने जा रहा है, तो निर्माणकर्ता के साथ इसे 10k पर सुरक्षित करने के लिए आरंभ करें। लेकिन अगर इसे 10k के लिए इनिशियलाइज़ किया जाता है तो आप 1k को 10k से अधिक लिखते हैं, यह फिर से आवंटित हो जाएगा और 20k सरणी में कॉपी हो जाएगा। इसलिए शुरुआती को कम करना बेहतर है।
ऑटो री-साइज़ के मामले में, 17 वें चरित्र में बैकिंग एरे फिर से आबंटित हो जाता है और 32 अक्षरों में कॉपी हो जाता है, 33 वें चरित्र में यह फिर से होता है और आपको 64 अक्षरों में एरे को फिर से आवंटित करने और कॉपी करने के लिए मिलता है। आप देख सकते हैं कि यह पुन: आवंटन और प्रतियों के बहुत से कैसे घटता है जो आप वास्तव StringBuilder/Buffer
में पहली जगह का उपयोग करने से बचने की कोशिश कर रहे हैं ।
यह AbstractDringBuilder के लिए JDK 6 स्रोत कोड से है
void expandCapacity(int minimumCapacity) {
int newCapacity = (value.length + 1) * 2;
if (newCapacity < 0) {
newCapacity = Integer.MAX_VALUE;
} else if (minimumCapacity > newCapacity) {
newCapacity = minimumCapacity;
}
value = Arrays.copyOf(value, newCapacity);
}
एक सबसे अच्छा अभ्यास यह है StringBuilder/Buffer
कि जितना आप सोचते हैं कि आपको जरूरत पड़ने वाली है उससे थोड़ा सा बड़ा इनिशियलाइज़ करना है अगर आपको सही पता नहीं है कि हाथ कितना बड़ा String
होगा लेकिन आप अनुमान लगा सकते हैं। आपकी आवश्यकता से थोड़ी अधिक मेमोरी का एक आवंटन पुनः आवंटन और प्रतियों के बहुत से बेहतर होने जा रहा है।
इसके StringBuilder/Buffer
साथ ही आरंभ करने से सावधान रहें, String
जो केवल स्ट्रिंग + 16 वर्णों के आकार को आवंटित करेगा, जो कि ज्यादातर मामलों में पतित पुन: आवंटन और प्रतिलिपि चक्र को शुरू करेगा जिसे आप बचने की कोशिश कर रहे हैं। निम्नलिखित जावा 6 स्रोत कोड से सीधा है।
public StringBuilder(String str) {
super(str.length() + 16);
append(str);
}
यदि आप संयोग से StringBuilder/Buffer
उस उदाहरण के साथ समाप्त हो जाते हैं, जिसे आपने नहीं बनाया है और जिसे कहा जाता है, उस निर्माणकर्ता को नियंत्रित नहीं कर सकता है, तो पतित-पुन: आवंटित और प्रतिलिपि व्यवहार से बचने का एक तरीका है। .ensureCapacity()
उस आकार के साथ कॉल करें जिसे आप सुनिश्चित करना चाहते हैं कि आपका परिणाम इसमें String
फिट होगा।
विकल्प:
एक नोट के रूप में, यदि आप वास्तव में भारी String
इमारत और हेरफेर कर रहे हैं, तो रोप्स नामक एक बहुत अधिक प्रदर्शन उन्मुख विकल्प है ।
एक अन्य विकल्प, StringList
उप-क्लासिंग द्वारा एक इम्प्लांटेशन बनाना है ArrayList<String>
, और .append()
सूची के हर और अन्य म्यूटेशन ऑपरेशंस पर वर्णों की संख्या को ट्रैक करने के लिए काउंटरों को जोड़ना है , फिर सूची के माध्यम से आपके द्वारा आवश्यक सटीक आकार और लूप बनाने और बनाने के .toString()
लिए ओवरराइड करें StringBuilder
आउटपुट, आप यह भी बना सकते हैं कि StringBuilder
एक इंस्टेंस वेरिएबल और 'कैशे' के परिणाम .toString()
और केवल कुछ परिवर्तन होने पर इसे फिर से जेनरेट करना होगा।
String.format()
फिक्स्ड फॉर्मेटेड आउटपुट का निर्माण करते समय यह भी न भूलें कि इसे बेहतर बनाने के लिए कंपाइलर द्वारा अनुकूलित किया जा सकता है।
String x = "A" + "B";
वास्तव में एक स्ट्रिंगब्यूलर बनना है? यह सिर्फ संकलन करने के लिए क्यों नहीं होगा String x = "AB";
, यह केवल एक स्ट्रिंगबर्न का उपयोग करना चाहिए यदि घटक संकलन समय पर ज्ञात नहीं हैं।
आप मतलब है, संघ के लिए?
वास्तविक दुनिया का उदाहरण: आप कई अन्य लोगों के लिए एक नया स्ट्रिंग बनाना चाहते हैं ।
उदाहरण के लिए एक संदेश भेजने के लिए:
तार
String s = "Dear " + user.name + "<br>" +
" I saw your profile and got interested in you.<br>" +
" I'm " + user.age + "yrs. old too"
StringBuilder
String s = new StringBuilder().append.("Dear ").append( user.name ).append( "<br>" )
.append(" I saw your profile and got interested in you.<br>")
.append(" I'm " ).append( user.age ).append( "yrs. old too")
.toString()
या
String s = new StringBuilder(100).appe..... etc. ...
// The difference is a size of 100 will be allocated upfront as fuzzy lollipop points out.
StringBuffer (वाक्य रचना StringBuilder के साथ के रूप में है, प्रभाव अलग)
के बारे में
StringBuffer
बनाम StringBuilder
पूर्व पर्यायवाची है और बाद में नहीं है।
इसलिए, यदि आप इसे एक ही धागे में कई बार लागू करते हैं (जो कि मामलों का 90% है), StringBuilder
तो बहुत तेज़ी से चलेगा क्योंकि यह देखने के लिए बंद नहीं होगा कि क्या यह थ्रेड लॉक का मालिक है।
इसलिए, इसका उपयोग करने की अनुशंसा की जाती है StringBuilder
(जब तक कि आपके पास एक ही समय में एक से अधिक थ्रेड इसे एक्सेस करने के लिए न हों, जो दुर्लभ है)
String
संघनन ( + ऑपरेटर का उपयोग करके ) को कम करने के लिए कंपाइलर द्वारा अनुकूलित किया जा सकता StringBuilder
है, इसलिए, जावा के बड़े दिनों में, इसके बारे में चिंता करने के लिए कुछ नहीं है, यह कुछ ऐसा था जो कहता है कि सभी को हर कीमत पर बचा जाना चाहिए, क्योंकि यह प्रतिपूर्ति एक नई स्ट्रिंग ऑब्जेक्ट बनाया। आधुनिक कंपाइलर अब ऐसा नहीं करते हैं, लेकिन फिर भी StringBuilder
केवल "पुराने" कंपाइलर का उपयोग करने के बजाय इसका उपयोग करना एक अच्छा अभ्यास है ।
संपादित करें
बस जो जिज्ञासु है, वह यह है कि इस वर्ग के लिए संकलक क्या करे:
class StringConcatenation {
int x;
String literal = "Value is" + x;
String builder = new StringBuilder().append("Value is").append(x).toString();
}
javap -c StringConcatenation
Compiled from "StringConcatenation.java"
class StringConcatenation extends java.lang.Object{
int x;
java.lang.String literal;
java.lang.String builder;
StringConcatenation();
Code:
0: aload_0
1: invokespecial #1; //Method java/lang/Object."<init>":()V
4: aload_0
5: new #2; //class java/lang/StringBuilder
8: dup
9: invokespecial #3; //Method java/lang/StringBuilder."<init>":()V
12: ldc #4; //String Value is
14: invokevirtual #5; //Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
17: aload_0
18: getfield #6; //Field x:I
21: invokevirtual #7; //Method java/lang/StringBuilder.append:(I)Ljava/lang/StringBuilder;
24: invokevirtual #8; //Method java/lang/StringBuilder.toString:()Ljava/lang/String;
27: putfield #9; //Field literal:Ljava/lang/String;
30: aload_0
31: new #2; //class java/lang/StringBuilder
34: dup
35: invokespecial #3; //Method java/lang/StringBuilder."<init>":()V
38: ldc #4; //String Value is
40: invokevirtual #5; //Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
43: aload_0
44: getfield #6; //Field x:I
47: invokevirtual #7; //Method java/lang/StringBuilder.append:(I)Ljava/lang/StringBuilder;
50: invokevirtual #8; //Method java/lang/StringBuilder.toString:()Ljava/lang/String;
53: putfield #10; //Field builder:Ljava/lang/String;
56: return
}
5 - 27 नंबर की रेखाएं "शाब्दिक" नाम के स्ट्रिंग के लिए हैं
"बिल्डर" नाम के स्ट्रिंग के लिए 31-53 की संख्याएँ हैं
थेर का कोई अंतर नहीं है, बिल्कुल एक ही कोड को दोनों तारों के लिए निष्पादित किया जाता है।
StringBuilder
पर असाइनमेंट के दाईं ओर स्ट्रिंग कंक्रीटिंग का उपयोग करने के लिए एक अच्छा अभ्यास नहीं है । जैसा कि आप कहते हैं, किसी भी अच्छे कार्यान्वयन के पीछे एक स्ट्रिंगबर्ल का उपयोग होगा। इसके अलावा, आपके उदाहरण "a" + "b"
को एक एकल शाब्दिक रूप में संकलित किया जाएगा, "ab"
लेकिन यदि आप इसका उपयोग करते हैं, StringBuilder
तो इसके परिणामस्वरूप दो अनावश्यक कॉल होंगे append()
।
"a"+"b"
लेकिन क्या एक था कहने के लिए स्ट्रिंग संयोजन के बारे में मैं बदल यह स्पष्ट किया जाना है। आप जो नहीं कहते हैं, वह यह करने के लिए एक अच्छा अभ्यास क्यों नहीं है। ठीक यही (एक आधुनिक) कंपाइलर करता है। @ फजी, मैं सहमत हूं, विशेष रूप से जब आप जानते हैं कि अंतिम स्ट्रिंग का आकार (aprox) क्या होगा।
-------------------------------------------------- -------------------------------- स्ट्रिंग स्ट्रिंगबर्फर स्ट्रिंग स्ट्रिंग -------------------------------------------------- -------------------------------- भंडारण क्षेत्र | लगातार स्ट्रिंग पूल हीप ढेर परिवर्तनशील | नहीं (अपरिवर्तनीय) हां (परस्पर) हां (परस्पर) धागा सुरक्षित | हां हां नहीं प्रदर्शन | बहुत तेज़ तेज़ -------------------------------------------------- --------------------------------
synchronised
और यही कारण है ।
तार
String class
चरित्र तार का प्रतिनिधित्व करता है। जावा प्रोग्राम में सभी स्ट्रिंग शाब्दिक, जैसे कि "abc"
इस वर्ग के उदाहरणों के रूप में कार्यान्वित किए जाते हैं।
स्ट्रिंग ऑब्जेक्ट्स अपरिवर्तनीय हैं एक बार जब वे बनाए जाते हैं तो हम बदल नहीं सकते हैं। ( तार लगातार होते हैं )
एक स्ट्रिंग निर्माता या विधि तो उन तार में संग्रहीत किया जाएगा का उपयोग कर बनाया गया है, तो ढेर मेमोरी के साथ ही SringConstantPool
। लेकिन पूल में बचत करने से पहले यह intern()
समान विधि के साथ पूल में समान सामग्री के साथ ऑब्जेक्ट उपलब्धता की जांच करने के लिए विधि को आमंत्रित करता है । यदि स्ट्रिंग में प्रतिलिपि-प्रति उपलब्ध है तो संदर्भ लौटाता है। अन्यथा, स्ट्रिंग ऑब्जेक्ट को पूल में जोड़ा जाता है और संदर्भ देता है।
+
) के लिए और स्ट्रिंग के लिए अन्य वस्तुओं के रूपांतरण के लिए विशेष सहायता प्रदान करती है । स्ट्रिंग संघात StringBuilder (या StringBuffer) वर्ग और उसके परिशिष्ट विधि के माध्यम से कार्यान्वित किया जाता है।String heapSCP = new String("Yash");
heapSCP.concat(".");
heapSCP = heapSCP + "M";
heapSCP = heapSCP + 777;
// For Example: String Source Code
public String concat(String str) {
int otherLen = str.length();
if (otherLen == 0) {
return this;
}
int len = value.length;
char buf[] = Arrays.copyOf(value, len + otherLen);
str.getChars(buf, len);
return new String(buf, true);
}
स्ट्रिंग शाब्दिक में संग्रहीत हैं StringConstantPool
।
String onlyPool = "Yash";
StringBuilder और StringBuffer वर्णों का परस्पर अनुक्रम है। इसका मतलब है कि कोई इन ऑब्जेक्ट के मूल्य को बदल सकता है। StringBuffer में StringBuilder जैसी ही विधियाँ हैं, लेकिन StringBuffer में प्रत्येक विधि सिंक्रनाइज़ की गई है, इसलिए यह सुरक्षित है।
StringBuffer और StringBuilder डेटा केवल नए ऑपरेटर का उपयोग करके बनाया जा सकता है। तो, वे हीप मेमोरी में संग्रहीत होते हैं।
StringBuilder के उदाहरण कई धागे द्वारा उपयोग के लिए सुरक्षित नहीं हैं। यदि इस तरह के सिंक्रोनाइज़ेशन की आवश्यकता होती है, तो यह अनुशंसा की जाती है कि स्ट्रिंगबफ़र का उपयोग किया जाए।
StringBuffer threadSafe = new StringBuffer("Yash");
threadSafe.append(".M");
threadSafe.toString();
StringBuilder nonSync = new StringBuilder("Yash");
nonSync.append(".M");
nonSync.toString();
StringBuffer और StringBuilder एक विशेष तरीके की तरह कर रहे हैं।,
replace(int start, int end, String str)
और reverse()
।
नोट : StringBuffer और SringBuilder परस्पर के रूप में वे के कार्यान्वयन प्रदान करता है
Appendable Interface
।
कब कौन सा उपयोग करना है
यदि आप हर बार मूल्य को बदलने नहीं जा रहे हैं तो इसका बेहतर उपयोग करना है String Class
। जेनेरिक के भाग के रूप में यदि आप Comparable<T>
किसी मान को क्रमबद्ध करना या तुलना करना चाहते हैं तो जाएं String Class
।
//ClassCastException: java.lang.StringBuffer cannot be cast to java.lang.Comparable
Set<StringBuffer> set = new TreeSet<StringBuffer>();
set.add( threadSafe );
System.out.println("Set : "+ set);
यदि आप StringBuilder के लिए हर बार मूल्य को संशोधित करने जा रहे हैं जो StringBuffer की तुलना में तेज़ है। यदि कई सूत्र StringBuffer के लिए मूल्य को संशोधित कर रहे हैं।
इसके अलावा, StringBuffer
धागा-सुरक्षित है, जो StringBuilder
नहीं है।
इसलिए एक वास्तविक समय की स्थिति में जब विभिन्न धागे इसे एक्सेस कर रहे होते हैं, StringBuilder
तो एक अनिर्दिष्ट परिणाम हो सकता है।
ध्यान दें कि यदि आप जावा 5 या नए का उपयोग कर रहे हैं, तो आपको StringBuilder
इसके बजाय उपयोग करना चाहिए StringBuffer
। एपीआई प्रलेखन से:
जारी होने के बाद JDK 5, इस वर्ग के, किसी एकल थ्रेड द्वारा इस्तेमाल के लिए डिजाइन एक समान वर्ग के साथ पूरक किया गया है
StringBuilder
।StringBuilder
वर्ग आम तौर पर, यह एक वरीयता में इस्तेमाल किया जाना चाहिए के रूप में यह एक ही कार्यों के सभी का समर्थन करता है, लेकिन यह तेजी से है, क्योंकि यह कोई तुल्यकालन प्रदर्शन करती है।
व्यवहार में, आप एक ही समय में कई थ्रेड्स से लगभग कभी भी इसका उपयोग नहीं करेंगे, इसलिए जो सिंक्रनाइज़ेशन StringBuffer
करता है वह लगभग हमेशा अनावश्यक ओवरहेड होता है।
व्यक्तिगत रूप से, मुझे नहीं लगता कि इसके लिए कोई वास्तविक विश्व उपयोग है StringBuffer
। जब मैं एक चरित्र अनुक्रम में हेरफेर करके कई थ्रेड्स के बीच संवाद करना चाहूंगा? यह सब उपयोगी नहीं लगता है, लेकिन शायद मैं अभी तक प्रकाश को देखने के लिए है :)
स्ट्रिंग और अन्य दो वर्गों के बीच अंतर यह है कि स्ट्रिंग अपरिवर्तनीय है और अन्य दो उत्परिवर्तनीय वर्ग हैं।
लेकिन हमारे पास एक ही उद्देश्य के लिए दो कक्षाएं क्यों हैं?
कारण यह है कि StringBuffer
थ्रेड सुरक्षित है और StringBuilder
नहीं है।
StringBuilder
पर एक नया वर्ग है StringBuffer Api
और इसे JDK5
हमेशा एक ही थ्रेडेड वातावरण में काम करने की सलाह दी जाती है क्योंकि यह बहुत हैFaster
पूर्ण विवरण के लिए आप http://www.codingeek.com/java/stringbuilder-and-stringbuffer-a-way-to-create-mutable-strings-in-java/ पढ़ सकते हैं
जावा में, स्ट्रिंग अपरिवर्तनीय है। अपरिवर्तनीय होने का मतलब है कि एक बार स्ट्रिंग बन जाने के बाद हम उसका मूल्य नहीं बदल सकते। StringBuffer म्यूट है। एक बार StringBuffer ऑब्जेक्ट बन जाने के बाद, हम सिर्फ एक नई ऑब्जेक्ट बनाने के बजाय ऑब्जेक्ट की वैल्यू को जोड़ते हैं। StringBuilder StringBuffer के समान है लेकिन यह थ्रेड-सुरक्षित नहीं है। StingBuilder के तरीके सिंक्रनाइज़ नहीं हैं, लेकिन अन्य स्ट्रिंग्स की तुलना में स्ट्रिंगर सबसे तेज़ चलता है। आप इन्हें लागू करके स्ट्रिंग, स्ट्रिंगबर्ल और स्ट्रिंगर के बीच अंतर जान सकते हैं ।