2008-10-31 6 views
30

मुझे बताया गया है कि कोड:जावा में, एक स्ट्रिंग x के लिए, s.length() की रनटाइम लागत क्या है? क्या यह ओ (1) या ओ (एन) है?

for (int i = 0; i < x.length(); i++) { 
    // blah 
} 

वास्तव में x (n^2) x.length() पर बार-बार कॉल की वजह से है। इसके बजाय मुझे इसका उपयोग करना चाहिए:

int l = x.length(); 
for (int i = 0; i < l; i++) { 
    // blah 
} 

क्या यह सच है? स्ट्रिंग लंबाई स्ट्रिंग क्लास के एक निजी पूर्णांक विशेषता के रूप में संग्रहीत है? या String.length() वास्तव में इसकी लंबाई निर्धारित करने के लिए पूरी स्ट्रिंग पर चलता है?

+1

स्ट्रिंग की लंबाई की गणना करने के बावजूद ओ (एन) था, कुल जटिलता अभी भी ओ (एन^2) नहीं होगी। लंबाई की गणना एक बार की जाती है और लूप के लिए सीमा मान के रूप में उपयोग की जाती है, इसकी गणना प्रत्येक पुनरावृत्ति पर नहीं की जाती है। –

+0

जहां तक ​​मुझे पता है, सीमा मान कैश नहीं किए जाते हैं। अगर लूप में सीमा को संशोधित किया गया तो क्या होगा? –

+2

सीमा हर समय गणना की जाती है। याद रखें, लूप की जांच सिर्फ मनमानी अभिव्यक्ति है। कंपाइलर वास्तव में परवाह नहीं करता है कि वहां क्या है, और धारणाएं नहीं बना सकती हैं। आप आसानी से एक विधि बुला सकते हैं जो हर बार कुछ अलग करता है। – Herms

उत्तर

51

नहीं, जावा स्ट्रिंग की लंबाई ओ (1) है क्योंकि जावा की स्ट्रिंग क्लास लंबाई को फ़ील्ड के रूप में संग्रहीत करती है।

आपको जो सलाह मिली है वह अन्य भाषाओं के अलावा सी नहीं है, बल्कि जावा नहीं है। सी के स्ट्रेलन चार सरणी के अंत में स्ट्रिंग चरित्र की तलाश में चलता है। जोएल ने पॉडकास्ट पर इसके बारे में बात की, लेकिन सी

+0

ध्यान दें कि कोड अभी भी प्रत्येक पुनरावृत्ति पर विधि कॉल निष्पादित करेगा (संकलक को पता नहीं है कि मान नहीं बदलेगा)। लूप नियंत्रण के बाहर कॉल को ले जाना विधि कॉल को खत्म कर देगा। ऐसा कहने के बाद, यह संभव नहीं है कि इस लूप के निष्पादन समय में अधिक परिवर्तन आएगा –

+5

एक आधुनिक जेआईटी शायद यह नोटिस करेगा कि लम्बाई (अंतिम) अंतिम अंतिम मूल्य लौटने वाले अंतिम वर्ग का एक साधारण गेटर है और इसे प्रतिस्थापित करता है int मूल्य के साथ विधि कॉल। –

+0

sk - मुझे लगता है कि एक ब्लॉग को देखने की याद आ रही है जिसने लंबाई() के जेआईटी अनुकूलन का परीक्षण किया और साबित किया कि यह सच था। –

-2

this के अनुसार, लंबाई स्ट्रिंग ऑब्जेक्ट का एक क्षेत्र है।

0

मुझे नहीं पता कि लिंक कितना अच्छा अनुवाद करेगा, लेकिन source of String#length देखें। संक्षेप में, #length() में ओ (1) जटिलता है क्योंकि यह सिर्फ एक फ़ील्ड लौट रही है। यह अपरिवर्तनीय तारों के कई फायदों में से एक है।

+0

अपरिवर्तनीयता के साथ इसके साथ कुछ लेना देना नहीं है। आपके पास एक म्यूटेबल स्ट्रिंग क्लास हो सकती है जो इसकी लंबाई का ट्रैक रखती है, वैसे ही जैसे आप एक अपरिवर्तनीय स्ट्रिंग (उदाहरण के लिए, स्ट्रिंगबिल्डर) के साथ कर सकते हैं। और आपके पास एक अपरिवर्तनीय स्ट्रिंग हो सकती है जो नहीं है (सी में चार * const)। – Herms

+0

लेकिन अपरिवर्तनीयता गारंटी देता है कि ऑब्जेक्ट बनने पर आपको केवल लंबाई के लिए मान की गणना करनी होगी। यदि वस्तु उत्परिवर्तनीय थी तो इसे एक म्यूटेटर विधि के प्रत्येक आमंत्रण के लिए एक नई गणना की आवश्यकता होगी। अब मुझे भुगतान करें या बाद में मुझे भुगतान करें क्योंकि कह रहा है। – laz

+0

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

12

अब तक जो कहा गया है उसके विपरीत, इस बात की कोई गारंटी नहीं है कि String.length() स्ट्रिंग में निहित वर्णों की संख्या में निरंतर समय संचालन है। String कक्षा के लिए या तो जावा भाषा विशिष्टता के लिए javadocs को निरंतर समय संचालन के लिए String.length की आवश्यकता होती है।

हालांकि, सूर्य के कार्यान्वयन में String.length() एक स्थिर समय ऑपरेशन है। आखिरकार, यह कल्पना करना मुश्किल है कि किसी भी कार्यान्वयन के लिए इस विधि के लिए निरंतर समय कार्यान्वयन क्यों होगा।

+2

इससे कोई फर्क नहीं पड़ता, मुझे लगता है कि * यह मानना ​​सुरक्षित है कि स्ट्रिंग। लम्बाई * आपके द्वारा दिए गए कारणों के लिए हमेशा * स्थिर समय रहेगा ...। –

4

आपको अवगत होना चाहिए कि length() विधि यूटीएफ -16 कोड बिंदुओं की संख्या लौटाती है, जो सभी मामलों में वर्णों की संख्या के समान नहीं है।

ठीक है, वास्तव में आपको प्रभावित करने की संभावनाएं बहुत पतली हैं, लेकिन इसे जानने में कोई हानि नहीं है।

+0

http://java.sun.com/javase/6/docs/api/java/lang/Character.html#unicode असल में, कुछ पात्रों को दो चार मानों द्वारा दर्शाया जाना चाहिए। चूंकि लंबाई() char [] सरणी का आकार है, यह वर्णों की संख्या के समान नहीं हो सकता है। लेकिन, जैसा कि सैडी ने कहा, यह बहुत दुर्लभ है। –

3

स्ट्रिंग लंबाई को एक अलग चर में स्टोर करता है। चूंकि स्ट्रिंग अपरिवर्तनीय है, लंबाई कभी नहीं बदलेगी। इसे बनाए जाने पर केवल लंबाई की गणना करने की आवश्यकता होगी, जो तब होता है जब स्मृति इसके लिए आवंटित की जाती है। इसलिए इसकी हे (1)

4

घटना आप पता नहीं था कि आप इसे इस तरह से लिख सकता है में:

for (int i = 0, l = x.length(); i < l; i++) { 
    // Blah 
} 

यह सिर्फ थोड़ा क्लीनर के बाद से l के दायरे में छोटा होता है है।

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