जावा में स्ट्रैटनिंग करते समय मेमोरी में कितने स्ट्रिंग्स बनाए जाते हैं?


17

मुझे जावा में अपरिवर्तनीय तारों के बारे में पूछा गया था। मुझे एक फंक्शन लिखने का काम सौंपा गया था, जो एक स्ट्रिंग के लिए "a" s की संख्या को समेटता है।

जो मैंने लिखा:

public String foo(int n) {
    String s = "";
    for (int i = 0; i < n; i++) {
        s = s + "a"
    }
    return s;
}

फिर मुझसे पूछा गया कि यह कार्यक्रम कितने तार उत्पन्न करेगा, यह मानते हुए कि कचरा संग्रहण नहीं होता है। N = 3 के लिए मेरे विचार थे

  1. ""
  2. "ए"
  3. "ए"
  4. "आ"
  5. "ए"
  6. "Aaa"
  7. "ए"

लूप के प्रत्येक पुनरावृत्ति में अनिवार्य रूप से 2 तार बनाए जाते हैं। हालाँकि, उत्तर n 2 था । इस फ़ंक्शन द्वारा मेमोरी में क्या तार बनाए जाएंगे और ऐसा क्यों है?


15
यदि आप इस नौकरी की पेशकश करते हैं, तो भाग जाओ, बहुत तेजी से
दौड़ें

कई कारणों से @mattnz (और केवल लिखित कोड के कारण नहीं)।

3
यह O (n ^ 2) रनटाइम लेता है जब तक कि JIT लूप का अनुकूलन नहीं करता है, लेकिन यह n ^ 2 स्ट्रिंग्स नहीं बनाता है।
user2357112

जवाबों:


26

फिर मुझसे पूछा गया कि यह कार्यक्रम कितने तार उत्पन्न करेगा, यह मानते हुए कि कचरा संग्रहण नहीं होता है। N = 3 के लिए मेरे विचार थे (7)

स्ट्रिंग्स 1 ( "") और 2 ( "a") कार्यक्रम में स्थिरांक हैं, इन्हें चीजों के हिस्से के रूप में नहीं बनाया जाता है, बल्कि 'इंटर्न' किया जाता है क्योंकि वे स्थिरांक हैं जिनके बारे में संकलक को पता है। विकिपीडिया पर स्ट्रिंग इंटर्निंग में इसके बारे में और पढ़ें ।

यह भी गिनती से 5 और 7 तार निकालता है क्योंकि वे "a"स्ट्रिंग # 2 के समान हैं । इससे # 3, # 4, और # 6 तार निकलते हैं। उत्तर है "3 कोड आपके कोड का उपयोग करके n = 3 के लिए बनाए गए हैं।"

N 2 की गिनती स्पष्ट रूप से गलत है क्योंकि n = 3 पर, यह 9 होगा और यहां तक ​​कि आपके सबसे खराब मामले के उत्तर से भी, यह केवल 7. था। यदि आपका गैर-आंतरिक तार सही था, तो उत्तर 2n + 1 होना चाहिए था।

तो, सवाल यह है कि आपको यह कैसे करना चाहिए ?

चूँकि स्ट्रिंग अपरिवर्तनीय है , आप एक परिवर्तनशील चीज़ चाहते हैं - कुछ ऐसी चीज़ जो आप नई वस्तुओं को बनाए बिना बदल सकते हैं। वह है स्ट्रिंगबर्ल

सबसे पहले गौर करने वाली बात यह है कि निर्माणकर्ता। इस मामले में हम जानते हैं कि स्ट्रिंग कितनी लंबी होगी, और एक कंस्ट्रक्टर है StringBuilder(int capacity) जिसका मतलब है कि हम जितना आवश्यक है उतना ही आवंटित करते हैं।

अगला, "a"एक स्ट्रिंग होने की आवश्यकता नहीं है , बल्कि यह एक चरित्र हो सकता है 'a'। यह कुछ मामूली प्रदर्शन जब बुला बढ़ाने है append(String)बनाम append(char)- साथ append(String), विधि का पता लगाने के कितनी देर स्ट्रिंग है और उस पर कुछ काम करने की जरूरत है। दूसरी ओर, charहमेशा एक वर्ण लंबा होता है।

कोड अंतर StringBuilder.append (स्ट्रिंग) बनाम StringBuilder.append (char) में देखे जा सकते हैं । यह कुछ के साथ बहुत चिंतित नहीं है, लेकिन अगर आप नियोक्ता को प्रभावित करने की कोशिश कर रहे हैं तो सर्वोत्तम संभव प्रथाओं का उपयोग करना सबसे अच्छा है।

तो, जब आप इसे एक साथ रखते हैं तो यह कैसा दिखता है?

public String foo(int n) {
    StringBuilder sb = new StringBuilder(n);
    for (int i = 0; i < n; i++) {
        sb.append('a');
    }
    return sb.toString();
}

एक StringBuilder और एक String बनाया गया है। कोई अतिरिक्त तार इंटर्न करने की आवश्यकता नहीं है।


ग्रहण में कुछ अन्य सरल कार्यक्रम लिखें। Pmd स्थापित करें और इसे आपके द्वारा लिखे गए कोड पर चलाएँ। ध्यान दें कि यह किस बारे में शिकायत करता है और उन चीजों को ठीक करता है। इसके साथ एक पाश में + एक स्ट्रिंग के संशोधन पाया होता है, और यदि आप StringBuilder है कि बदल गया है, यह है | शायद आरंभिक क्षमता पाया है, लेकिन यह निश्चित रूप से के बीच अंतर को पकड़ने होगा .append("a")और.append('a')


9

प्रत्येक पुनरावृत्ति पर, ऑपरेटर Stringद्वारा एक नया बनाया जाता है +और उसे सौंपा जाता है s। वापसी के बाद, उन सभी को लेकिन अंतिम कचरा एकत्र किया जाता है।

स्ट्रिंग स्थिरांक की तरह ""और "a"हर बार नहीं बनाया जाता है, ये आंतरिक तार हैं । चूंकि तार अपरिवर्तनीय हैं, उन्हें स्वतंत्र रूप से साझा किया जा सकता है; यह स्ट्रिंग स्थिरांक के साथ होता है।

कुशलता से तार का उपयोग करने के लिए, का उपयोग करें StringBuilder


साक्षात्कार में लोगों ने वास्तव में इस बात पर बहस की कि क्या शाब्दिक है या नहीं, और फैसला किया कि शाब्दिक हर बार बनाए गए थे। लेकिन यह अधिक समझ में आता है।
३:२० बजे अल्बर्ट रॉबर्ट २

6
आप "बहस" कैसे करते हैं कि कोई भाषा क्या करती है, निश्चित रूप से आप विनिर्देश पढ़ते हैं और सुनिश्चित करने के लिए जानते हैं, या इसके परिभाषित नहीं हैं और इसलिए, कोई सही उत्तर नहीं है .....
मैट्नज़

@mattnz यह जानना दिलचस्प हो सकता है कि आप संकलक / रनटाइम का क्या उपयोग कर रहे हैं, भले ही वह विवरणों को लागू करने की बात हो। यह विशेष रूप से प्रदर्शन पर लागू होता है।
svick

1
@ शविक: आप मान्यताओं को बनाकर बहुत कुछ हासिल कर सकते हैं, फिर कंपाइलर को अपग्रेड किया जाता है, एक ऑप्टिमाइज़ेशन बदला जाता है। व्यवहार में बदलाव होता है क्योंकि आप अनिर्दिष्ट व्यवहार के बजाय अनिर्दिष्ट व्यवहार पर निर्भर होते हैं। आप जानते हैं कि वे अनुकूलन के बारे में क्या कहते हैं - ए) इसे विशेषज्ञों पर छोड़ दें और बी) आपके विशेषज्ञ अभी तक नहीं। :) यदि निर्भरता केवल प्रदर्शन पर आधारित है, लेकिन फिर भी भाषा विनिर्देश पर आधारित है, तो आप केवल ढीला प्रदर्शन करते हैं। कई बार मैंने ऐसे कोड देखे हैं जो अनपेक्षित या कंपाइलर विशिष्ट व्यवहार पर निर्भर करते हुए अप्रत्याशित तरीके (ज्यादातर C और C ++) पर निर्भर करते हैं।
21

@mattnz तो आप प्रदर्शन से संबंधित निर्णय लेने का प्रस्ताव कैसे करते हैं? आमतौर पर, आप विनिर्देश / दस्तावेज़ीकरण से जो सर्वश्रेष्ठ प्राप्त कर सकते हैं वह बड़ी-हे जटिलताएँ हैं, लेकिन यह पर्याप्त नहीं है। किसी भी मामले में, प्रदर्शन हमेशा कार्यान्वयन पर निर्भर करेगा, इसलिए मुझे लगता है कि निष्पादन के विवरण पर भरोसा करना ठीक है जब यह प्रदर्शन की बात आती है।
svick

4

जैसा कि माइकलटी अपने जवाब में बताते हैं, आपका कोड O (n) स्ट्रिंग्स आवंटित करता है। लेकिन यह O (n 2 ) मेमोरी का बाइट भी आवंटित करता है और O (n 2 ) समय में चलता है ।

यह O (n 2 ) बाइट्स को आवंटित करता है , क्योंकि आपके द्वारा आवंटित किए जाने वाले तार की लंबाई 0, 1, 2,…, n-1, n है, जो (n 2 + n) / 2 = O (n 2 ) के लिए होती है।

समय भी O (n 2 ) है, क्योंकि i-th स्ट्रिंग आवंटित करने के लिए (i-1) -th स्ट्रिंग की प्रतिलिपि की आवश्यकता होती है, जिसकी लंबाई i-1 है। इसका अर्थ है कि प्रत्येक आवंटित बाइट की प्रतिलिपि बनाई जानी है, जिसमें O (n 2 ) समय लगेगा।

शायद यह साक्षात्कारकर्ताओं का क्या मतलब है?


नहीं समीकरण (एन ^ 2 + एन) / 2, की तरह होना चाहिए यहाँ ?
हेयूड जूल
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.