मेरे पास एक वर्ग है जो कक्षा की विशेषताओं की एक सूची रखता है। ये सुविधाएँ पढ़ने की तुलना में बार-बार बदलती हैं। फीचर सूची के माध्यम से रीड्स लगभग हमेशा पुनरावृत्तियों होते हैं। इस वजह से, मैं CopyOnWriteArrayList का उपयोग कर रहा हूं।

मैं इस तरह एक समारोह करना चाहता हूँ:

function Feature[] getFeatures() {
  .. implementation goes here ..
}

मैं मानता हूँ, इसका कारण थोड़ा आलस्य हो सकता है। मैं इस तरह कोड लिखना चाहता हूं:

for (Feature f: object.getFeatures()) {
  .. do something interesting ..
}

इसके बजाय:

Iterator<Feature> iter = object.getFeatureIterator();
while (iter.hasNext()) {
  Feature f = iter.next();
  .. do something interesting ..
}

मुख्य प्रश्न है - क्या मैं यहाँ आलसी हो रहा हूँ? मैं इस पैटर्न का बहुत पालन करने जा रहा हूं, और मुझे लगता है कि कोड का पहला हिस्सा बनाए रखना बहुत आसान है। जाहिर है, मैं अंतर्निहित सरणी को कभी नहीं बदलूंगा, और मैं इसे दस्तावेज़ीकरण में रखूंगा।

इस स्थिति को संभालने का सही तरीका क्या है?

1
Erick Robertson 19 नवम्बर 2011, 03:43

5 जवाब

सबसे बढ़िया उत्तर

सूची में बस toArray विधि को कॉल करें:

public Feature[] getFeatures() {
    return this.featureList.toArray(new Feature[this.featureList.size()]);
}

ध्यान दें कि foreach सिंटैक्स का उपयोग सभी Iterable ऑब्जेक्ट्स के साथ किया जा सकता है, और List Iterable है, इसलिए आपके पास बस हो सकता है

public List<Feature> getFeatures() {
    return this.features;
}

और उसी फ़ोरैच लूप का उपयोग करें। यदि आप नहीं चाहते कि कॉल करने वाले आंतरिक सूची को संशोधित करें, तो सूची का एक अपरिवर्तनीय दृश्य लौटाएं:

public List<Feature> getFeatures() {
    return Collections.unmodifiableList(this.features);
}
1
JB Nizet 19 नवम्बर 2011, 03:52

मुझे आपका कारण समझ में नहीं आया: एक List<Feature> लौटाएं, अपनी CopyOnWriteArrayList या एक अपरिवर्तनीय प्रतिलिपि का उपयोग करें, और foreach का उपयोग करें। आप विशेष रूप से एक सरणी क्यों चाहते हैं?

1
Dave Newton 19 नवम्बर 2011, 03:51

क्लास CopyOnWriteArrayList इम्प्लीमेंट्स Iterable, जो कि आपको शक्करयुक्त for लूप सिंटैक्स का उपयोग करने की आवश्यकता है। ऊपर वर्णित मामले में आपको स्पष्ट रूप से Iterator पकड़ने की आवश्यकता नहीं है।

क्या आपने पाया कि यह संकलित नहीं करता है?

1
seh 19 नवम्बर 2011, 03:53

आप सूची का क्लोन बना सकते हैं

public List<Feature> getFeatures() {
    return (List<Feature>)this.features.clone();
}

एक copyOnWriteArrayList को क्लोन करना अंतर्निहित सरणी की प्रतिलिपि नहीं बनाता है

1
ratchet freak 19 नवम्बर 2011, 04:03

CopyOnWriteArrayList ऑब्जेक्ट की कॉपी-ऑन-राइट (गाय) प्रकृति का अर्थ है कि सूची के प्रत्येक संशोधन पर आपको सभी प्रविष्टियों के साथ इसके अंतर्निहित सरणी का एक नया उदाहरण मिलता है, लेकिन संशोधन पिछले उदाहरण से कॉपी किया गया है।

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

(इसके विपरीत, for (int i = 0; i < list.size(); ++i) doSomethingWith(list.get(i)); जैसा लूप आपको अन्य थ्रेड्स के संशोधनों से नहीं बचाता है, और यदि आप list.size() को कॉल करने और संबंधित list.get(i), कुछ तत्व हटा दिए गए हैं!)

चूंकि प्रत्येक शैली के लिए फॉर-लूप कवर के तहत इटरेटर का उपयोग करता है, इसलिए आपको यह सुसंगतता गारंटी मिलती है। आप इसे forEach() विधि का उपयोग करते समय भी प्राप्त करते हैं। यह forEach() के समय उपलब्ध सरणी के भीतर (सरणी अनुक्रमण का उपयोग करके) पुनरावृति करता है।

अंत में, clone() विधि अनिवार्य रूप से एक समान स्नैपशॉट लेती है। यदि आपका कोड ही एकमात्र स्थान है जहां आप क्लोन संस्करण का उपयोग करते हैं, या आप इसे अपरिवर्तनीय बनाते हैं, तो आप मूल स्नैपशॉट से परामर्श करेंगे। मूल की गाय प्रकृति आपकी प्रतिलिपि को मूल में परिवर्तन से बचाती है। अगर आप clone() पर भरोसा नहीं करना चाहते हैं, जिसमें copyonw">मुद्दों, आप सूची डेटा की प्रतिलिपि बना सकते हैं, लेकिन इसमें कम से कम किसी अन्य आवंटन के साथ सरणी की प्रतिलिपि बनाना शामिल है।

0
Tony Balinski 9 अगस्त 2019, 11:37