जावा में लिंक्डलिस्ट की एक सरणी नहीं बना सकते ...?


102

मैं एक विरल मैट्रिक्स वर्ग पर काम कर रहा हूं , जिसे मैट्रिक्स के मूल्यों को संग्रहीत करने के लिए एक सरणी का उपयोग करने की आवश्यकता है LinkedList। सरणी का प्रत्येक तत्व (यानी प्रत्येक LinkedList) मैट्रिक्स की एक पंक्ति का प्रतिनिधित्व करता है। और, LinkedListसरणी में प्रत्येक तत्व एक स्तंभ और संग्रहीत मान का प्रतिनिधित्व करता है।

मेरी कक्षा में, मेरे पास ऐरे की घोषणा है:

private LinkedList<IntegerNode>[] myMatrix;

और, मेरे निर्माता में SparseMatrix, मैं परिभाषित करने की कोशिश करता हूं:

myMatrix = new LinkedList<IntegerNode>[numRows];

मुझे जो त्रुटि मिल रही है वह है

का एक सामान्य सरणी नहीं बना सकता LinkedList<IntegerNode>

इसलिए, मेरे पास इसके साथ दो मुद्दे हैं:

  1. मैं क्या गलत कर रहा हूँ, और
  2. यदि यह नहीं बनाया जा सकता है तो सरणी के लिए घोषणा में प्रकार स्वीकार्य क्यों है?

IntegerNodeएक वर्ग है जिसे मैंने बनाया है। और, मेरी सभी क्लास फाइलें एक साथ पैक की जाती हैं।

जवाबों:


64

आप सामान्य सरणी निर्माण का उपयोग नहीं कर सकते। यह जावा जेनरिक का दोष / विशेषता है।

चेतावनियों के बिना तरीके हैं:

  1. सूचियों की श्रेणी के बजाय सूचियों की सूची का उपयोग करना:

    List< List<IntegerNode>> nodeLists = new LinkedList< List< IntegerNode >>();
  2. सूचियों की श्रेणी के लिए विशेष वर्ग की घोषणा:

    class IntegerNodeList {
        private final List< IntegerNode > nodes;
    }
    

19
बाद के समाधान के लिए एक बेहतर विकल्प होगा: class IntegerNodeList extends List<IntegerNode> {}
kamasheto

यह कार्यान्वयन अपमानजनक रूप से धीमा है। [१०००] [२०००] तत्व (नोडलिस्ट्स .get (१०००) .get (२०००)) प्राप्त करना लिंक्डलिस्ट को ३००० बार पुनरावृत्त कर देगा! अगर किसी को इसमें अनुक्रमित किया जा सकता है तो लिंक्डलिस्ट से बचें। ArrayList तेजी से सूचकांक करेगा, लेकिन फ्रेड्रिक का समाधान समग्र रूप से बेहतर है।
स्टीव ज़ॉबेल

142

किसी कारण से आपको टाइप करना होगा और इस तरह घोषणा करनी होगी:

myMatrix = (LinkedList<IntegerNode>[]) new LinkedList<?>[numRows];

मैंने इसी तरह की समस्या पर शोध किया और पढ़ा कि उपरोक्त कास्ट एक बहुत ही सामान्य 'हैक' है जिसका उपयोग सभी संग्रह रूपरेखाओं में किया जाता है।
ल्यूक

15
IMO, यह चयनित उत्तर होना चाहिए। मैंने प्रयोग नहीं किया है, लेकिन मुझे यह महसूस करना है कि सर्गेई का # 2 तरीका काफी हद तक उपरि बनाता है; और मुझे लगता है कि # 1 करता है। एक सूची कई मायनों में एक सरणी के रूप में कुशल नहीं है जिसे मैं यहां विस्तार नहीं करूंगा, लेकिन मैंने प्रयोग किए हैं और सरणियों की तुलना में सूचियों का उपयोग करते समय बड़े मंदी देखी है। यह केवल अपने स्वयं के सरणियों का प्रबंधन करने और उन्हें पुनः सूचीबद्ध करने की तुलना में सूची में सामान जोड़ने के लिए तेज़ है।
Ricket

@Ricket मैं मानता हूँ, से लिया ibm.com/developerworks/java/library/j-jtp01255/index.html
Peteter

4
मुझे अभी भी एक "टाइप सेफ्टी: अनियंत्रित कास्ट" चेतावनी मिली है। बॉब का समाधान मुझे सबसे साफ दिखता है।
मार्को लैकोविच

3
JDK 7 में उपरोक्त एक रॉटाइप्स चेतावनी देता है। यह अनबाउंड <?> प्रकार का उपयोग करके तय किया जा सकता है, लेकिन आपको अभी भी अनियंत्रित चेतावनी मिलती है (जिसे दबाया जा सकता है)। उदाहरण के लिए <br> <code> myMatrix = (LinkedList <IntegerNode> []) नया लिंक्डलिस्ट <?> [संख्या]; </ कोड>
नियॉन

5

सिंटैक्स समस्याओं के अलावा, मुझे एक मैट्रिक्स का प्रतिनिधित्व करने के लिए एक सरणी और एक लिंक की गई सूची का उपयोग करना अजीब लगता है। मैट्रिक्स की मनमानी कोशिकाओं तक पहुंचने में सक्षम होने के लिए, आप संभवतः एक वास्तविक सरणी चाहते हैं या कम से कम ArrayListपंक्तियों को पकड़ना चाहते हैं, क्योंकि LinkedListपूरी सूची को पहले तत्व से किसी विशेष तत्व तक पहुंचाना चाहिए, एक O(n)ऑपरेशन, जितना विरोध किया जाता है। तेज O(1)के साथ ArrayListया एक वास्तविक सरणी।

चूंकि आपने उल्लेख किया है कि यह मैट्रिक्स विरल है, हालांकि, शायद डेटा को स्टोर करने का एक बेहतर तरीका मैप्स के मानचित्र के रूप में है, जहां पहले मैप में एक कुंजी एक पंक्ति सूचकांक का प्रतिनिधित्व करती है, और इसका मान एक पंक्ति मानचित्र है जिसकी कुंजी एक कॉलम इंडेक्स है , मान के साथ आपका IntegerNode क्लास है। इस प्रकार:

private Map<Integer, Map<Integer, IntegerNode>> myMatrix = new HashMap<Integer, Map<Integer, IntegerNode>>();

// access a matrix cell:
int rowIdx = 100;
int colIdx = 30;
Map<Integer, IntegerNode> row = myMatrix.get(rowIdx); // if null, create and add to matrix
IntegerNode node = row.get(colIdx); // possibly null

यदि आपको पंक्ति द्वारा मैट्रिक्स पंक्ति को पार करने में सक्षम होने की आवश्यकता है TreeMap, तो आप अनुक्रमणिका क्रम में स्तंभों को ट्रैवर्स करने के लिए पंक्ति मानचित्र को एक प्रकार बना सकते हैं , और यदि आपको उन मामलों की आवश्यकता नहीं है, तो इससे HashMapभी तेज है TreeMap। एक अशक्त मान प्राप्त करने और एक मनमाना सेल स्थापित करने के लिए सहायक तरीके, निश्चित रूप से उपयोगी होंगे।



3

myMatrix = (LinkedList<IntegerNode>[]) new LinkedList[numRows];

इस तरह से कास्टिंग करना काम करता है लेकिन फिर भी आपको एक बुरा चेतावनी देता है:

"प्रकार सुरक्षा: प्रकार सूची की अभिव्यक्ति [] अनियंत्रित रूपांतरण की आवश्यकता है .."

सूचियों की श्रेणी के लिए एक विशेष वर्ग की घोषणा:

class IntegerNodeList { private final List< IntegerNode > nodes; }

चेतावनी से बचने के लिए एक चतुर विचार है। शायद इसके लिए एक इंटरफ़ेस का उपयोग करना थोड़ा अच्छा है:

public interface IntegerNodeList extends List<IntegerNode> {}

फिर

List<IntegerNode>[] myMatrix = new IntegerNodeList[numRows];

चेतावनियों के बिना संकलन।

बहुत बुरा नहीं लगता है, यह करता है?


IntegerNodeList: आप किस वर्ग के साथ इसका उपयोग करेंगे? उदाहरण के लिए आप एक ArrayList <IntegerNode> को असाइन नहीं कर सकते। आपको ArrayList का विस्तार करने की आवश्यकता होगी ...
हंस-पीटर स्टॉरर

सरणी के आरंभीकरण के बाहर इंटरफ़ेस IntegerNodeList का उपयोग करने की कोई आवश्यकता नहीं है: सूची <IntegerNode> [] myMatrix = नया IntegerNodeList [5]; for (int i = 0; मैं <myMatrix.length; i ++) {myMatrix [i] = new ArrayList <IntegerNode> (); }
user306708

1
List<IntegerNode>[] myMatrix = new IntegerNodeList[numRows];यह एक सूक्ष्म लेकिन महत्वपूर्ण समस्या है। आप केवलIntegerNodeList सरणी में रख सकते हैं । myMatrix[i] = new ArrayList<IntegerNode>();फेंक देंगे ArrayStoreException
रेडियोएडफ़

2
List<String>[] lst = new List[2];
lst[0] = new LinkedList<String>();
lst[1] = new LinkedList<String>();

कोई चेतावनी नहीं। नेटबियंस 6.9.1, jdk1.6.0_24


1
यह सच है कि कोई चेतावनी नहीं है, लेकिन ओरेकल के जावा एसई 6 अपडेट 32 के साथ मुझे संकलित त्रुटि मिलती है "प्रकार सूची सामान्य नहीं है; इसे तर्कों के साथ मानकीकृत नहीं किया जा सकता है <स्ट्रिंग>"। <स्ट्रिंग> तर्क को हटाने से एक और त्रुटि उत्पन्न होती है "टाइप मिसमैच: लिंक्डलिस्ट से नहीं बदला जा सकता है <स्ट्रिंग> सूची से"।
मार्को लैकोविच


0

यदि मैं निम्नलिखित करता हूं तो मुझे प्रश्न में त्रुटि संदेश मिलता है

LinkedList<Node>[] matrix = new LinkedList<Node>[5];

लेकिन अगर मैं घोषणा में सूची प्रकार को हटाता हूं तो यह वांछित कार्यक्षमता है।

LinkedList<Node>[] matrix = new LinkedList[5];

क्या ये दोनों घोषणाएं एक तरह से अलग हैं, जिनके बारे में मुझे जानकारी नहीं है?

संपादित करें

आह, मुझे लगता है कि मैं इस मुद्दे में अब भाग गया हूं।

मैट्रिक्स पर इरेटिंग और एक लूप में सूचियों को आरंभीकृत करने से काम करने लगता है। हालांकि यह कुछ अन्य समाधानों की तरह आदर्श नहीं है।

for(int i=0; i < matrix.length; i++){

    matrix[i] = new LinkedList<>();
}

0

आपको सूची की एक सरणी की आवश्यकता है, एक विकल्प का प्रयास करना है:

private IntegerNode[] node_array = new IntegerNode[sizeOfYourChoice];

फिर या (जो भी आपकी पसंदीदा सूची कार्यान्वयन हो) node_array[i]के सिर (पहले) नोड को संग्रहीत करता है । ArrayList<IntegerNode>LinkedList<IntegerNode>

इस डिज़ाइन के तहत, आप यादृच्छिक अभिगम विधि खो देते हैं list.get(index), लेकिन फिर भी आप सूची को सुरक्षित प्रकार में सिर / मुट्ठी नोड स्टोर से शुरू कर सकते हैं।

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

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.