2012-04-01 20 views
5

मैं ArrayList से एक वस्तु अगर मैं पाश के लिए उपयोग "सामान्य" जब काम पर काम कर को हटाने के साथ कोई समस्या है, यहनिकाला जा रहा है ArrayList वस्तु मुद्दा

public void returnBook(String isbn){   
    for (int i = 0; i < booksBorrowed.size(); i++){    
     if (booksBorrowed.get(i).getISBN() == isbn){ 
      booksBorrowed.get(i).returnBook(); 
      booksBorrowed.remove(i);     
     } 
    } 
} 

निम्नलिखित हालांकि, जब मैं कर रहा हूँ के रूप में काम वह काम नहीं करता साथ के लिए लूप बढ़ाया कोड को आसान बनाने की कोशिश कर रहा है, और दिखा java.util.ConcurrentModificationException त्रुटि:

public void returnBook(String isbn){   
     for (Book book: booksBorrowed){    
      if (book.getISBN() == isbn){ 
       book.returnBook(); 
       booksBorrowed.remove(book);     
      } 
     } 
} 

आशा है कि आप लोग मुझे ऊपर हल्का कर सकता है ..

+0

अगर आपका प्रश्न "क्यों मैं एक त्रुटि मिलता है" है यह है क्योंकि आप उस सूची से आइटम नहीं हटा सकते हैं जिस पर आप पुन: प्रयास कर रहे हैं। और यदि आपके पास एक ही आईएसबीएन सूची में दो बार हो सकता है, तो आपके पहले लूप में एक बग हो सकता है। –

उत्तर

7

आपका विकल्प करना woud हैं:

List<Book> books = new ArrayList<Book>(); 
books.add(new Book(new ISBN("0-201-63361-2"))); 
books.add(new Book(new ISBN("0-201-63361-3"))); 
books.add(new Book(new ISBN("0-201-63361-4"))); 

सभी रिकॉर्ड है कि आप पाश के लिए बढ़ाया पर नष्ट करना चाहते एकत्रित करें, और पुनरावृत्ति आप समाप्त करने के बाद , आप सभी पाए गए रिकॉर्ड्स को हटा दें।

ISBN isbn = new ISBN("0-201-63361-2"); 
List<Book> found = new ArrayList<Book>(); 
for(Book book : books){ 
    if(book.getIsbn().equals(isbn)){ 
     found.add(book); 
    } 
} 
books.removeAll(found); 

या आप एक ListIterator जो यात्रा के दौरान ही एक निकालें विधि के लिए समर्थन हासिल है का उपयोग कर सकते हैं।

ListIterator<Book> iter = books.listIterator(); 
while(iter.hasNext()){ 
    if(iter.next().getIsbn().equals(isbn)){ 
     iter.remove(); 
    } 
} 

या आप LambdaJ की तरह एक तीसरे पक्ष के पुस्तकालय का उपयोग कर सकते हैं और यह पर्दे के पीछे आप के लिए सब काम करता है>

List<Book> filtered = select(books, 
       having(on(Book.class).getIsbn(), 
         is(new ISBN("0-201-63361-2")))); 
+0

धन्यवाद दोस्त, समस्या हल हो गई है :) – babygau

+0

आप मेरी जान बचाओ। धन्यवाद –

4

आपको वास्तव में ऐसा नहीं करना चाहिए क्योंकि वे अंत में समस्याएं पैदा करेंगे। इसके बजाय सूची के माध्यम से पुन: प्रयास करने में सहायता के लिए ArrayList के पुनरावर्तक का उपयोग करें और फिर केवल इटरेटर के साथ हटा दें। यह हानिकारक समवर्ती संशोधन त्रुटियों को रोकने में मदद करेगा।

+1

/गोल्फक्लप 'pernicious' का उपयोग –

0

जब आप जावा में उन्नत फॉर-लूप का उपयोग कर रहे हैं तो यह सूची में पुनरावर्तित करने के लिए सूची के इटरेटर का उपयोग करता है। जब आप सूची के निकाले गए फ़ंक्शन के साथ कोई आइटम हटाते हैं, तो यह इटरेटर की स्थिति में हस्तक्षेप करेगा और इटेटरेटर एक समवर्ती मोडिफिकेशन एक्सेप्शन फेंक देगा। सरल फॉर-लूप के साथ आपको ऐसी समस्या नहीं है क्योंकि आप केवल सूची का उपयोग कर रहे हैं और राज्य परिवर्तन केवल सूची में ही होता है।

for (int i = 0; i < booksBorrowed.size(); i++){    
    if (booksBorrowed.get(i).getISBN() == isbn){ 
     booksBorrowed.get(i).returnBook(); 
     booksBorrowed.remove(i);     
    } 
} 

इसे हटा दिया लोगों के बाद अगले तत्वों को छोड़ देता है:

+0

बुक ऑब्जेक्ट – babygau

+0

को हटाने के लिए इटरेटर का उपयोग करने के तरीके के साथ मुझे थोड़ा सा ज्ञान प्रदान करने के लिए यह वास्तव में निर्भर करता है कि आप किस एप्लिकेशन और आप किस प्रकार के प्रदर्शन चाहते हैं। हैशपैप और सरणीसूची इटरेटर का संयोजन ऐसा करेगा। – amshali

1

आप अपने कोड में एक बग है। जैसे जब आपने '0 वें' तत्व को हटा दिया, तो पहला 0 वां हो जाता है, लेकिन यह कोड इसके माध्यम से पुनरावृत्ति नहीं करता है।

यह एक सही संस्करण है:

for (int i = booksBorrowed.size() - 1; i >= 0; i--){    
    if (booksBorrowed.get(i).getISBN() == isbn){ 
     booksBorrowed.get(i).returnBook(); 
     booksBorrowed.remove(i);     
    } 
} 

लेकिन यह सबसे अच्छा तरीका है, क्योंकि यह जटिलता O (n^2) है नहीं है।

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

पीएस प्रत्येक निर्माण के लिए इसे हटाने वाला इटरेटर तोड़ता है, इसलिए इस मामले में सूची को संसाधित करने का यह वैध तरीका नहीं है।

लेकिन आप निम्न कर सकते हैं:

for (Iterator<String> i = a.iterator(); i.hasNext();) { 
     Book next = i.next(); 
     if (book.getISBN() == isbn){ 
      book.returnBook(); 
      i.remove(i);     
     } 
    } 

फिर, जटिलता O (n^2) इस मामले में है।

+0

पहला पाश काम करता है अगर वह उबेर-सकल "i--;" जोड़ता है अगर कथन के नीचे। –

+0

आपका क्या मतलब है? –

+0

आखिरी में, क्या यह ArrayList से या केवल इटेटरेटर से हटा देता है? –

2

सभी अच्छे उत्तरों। लेकिन मैं आपको पुनर्विचार करने के लिए मजबूर करूंगा। मेरा मतलब है, क्या आपको वास्तव में एक ऐरेलिस्ट की आवश्यकता है या हैश मैप बेहतर होगा? यदि आपकी ऑब्जेक्ट्स की सूची में एक यूनिक कुंजी (आईएसबीएन) है, और आप प्रत्येक ऑब्जेक्ट प्राप्त करने के लिए इसका उपयोग करते हैं, तो अपनी समस्या के लिए एक संग्रह का उपयोग क्यों न करें?

आप एक ConcurrentModificationException से बचने के लिए केवल इस

public void returnBook(String isbn){   
    Book book = (Book) booksBorrowed.remove(isbn);    
    book.returnBook();  
} 
संबंधित मुद्दे