2016-01-16 15 views
8

मैं निम्नलिखित कोड और जावा 8 का उपयोग बिना किसी समस्या के उपयोगकर्ताओं की सूची को सॉर्ट कर सकते हैं:संग्रह .sort (सूची) जावा 8 में CopyOnWriteArrayList के साथ क्यों काम करता है लेकिन जावा 7 में नहीं?

CopyOnWriteArrayList<User> allCurrentLoginnedUsersList = new CopyOnWriteArrayList<>(); 
Collections.sort(allCurrentLoginnedUsersList); 

अब, मैं जावा 7 के लिए बदल दिया और मैं ग्रहण पर कोई त्रुटि देखा। लेकिन अब, जब जावा 7 के तहत चल रहा है तो मुझे यह त्रुटि मिली:

java.lang.UnsupportedOperationException 
    at java.util.concurrent.CopyOnWriteArrayList$COWIterator.set(CopyOnWriteArrayList.java:1049) 
    at java.util.Collections.sort(Collections.java:221) 
    at com.fluent.User.sortAllCurrentLoginnedUsers(User.java:446) 

इसे कैसे ठीक करें?

उत्तर

12

जावा 7 (और जावा 8 के प्रारंभिक संस्करण) (के रूप में Holger द्वारा नोट issue 8032636,) जिस तरह से Collections.sort काम में और जावा 8u20 के बीच एक परिवर्तन था।


जावा 7 Collections.sort(list, c) यह बताता है कि:

This implementation dumps the specified list into an array, sorts the array, and iterates over the list resetting each element from the corresponding position in the array. This avoids the n² log(n) performance that would result from attempting to sort a linked list in place.

Looking at the code, इस सूची में से एक ListIterator प्राप्त करने के द्वारा किया जाता है। हालांकि, CopyOnWriteArrayListlistIterator() विधि कहा गया है कि इटरेटर लौटे set आपरेशन का समर्थन नहीं करता:,

The returned iterator provides a snapshot of the state of the list when the iterator was constructed. No synchronization is needed while traversing the iterator. The iterator does NOT support the remove , set or add methods.

यह त्रुटि आप जब जावा 7. के साथ अपने कोड चल समाधान के लिए हो रही है बताते हैं आप this question जहां का उल्लेख कर सकते जवाब सूची की सामग्री को सरणी में डंप करना है, सरणी को सॉर्ट करें और तत्वों को सूची में वापस रखें।

This implementation defers to the List.sort(Comparator) method using the specified list and comparator.

और नई विधि CopyOnWriteArrayList.sort(c) (जावा 8 से प्रारंभ) सूची इटरेटर का उपयोग नहीं करता है, तो यह सही ढंग से काम करता है:


जावा 8 में, Collections.sort(list, c) कार्यान्वयन बदल दिया है।

2

Collections.sort(), जावा 7 (और जावा 8 के शुरुआती संस्करण) सूची सूची को संशोधित करने के लिए सूची इटरेटर के set() का उपयोग करता है। लेकिन CopyOnWriteArrayList के इटेटर को स्पष्ट रूप से इस ऑपरेशन का समर्थन नहीं करने के रूप में दस्तावेज किया गया है।

इसे कैसे ठीक करें? अपने CopyOnWriteArrayList को नियमित ऐरेलिस्ट या सरणी में बदलें, इसे सॉर्ट करें, और फिर CopyOnWriteArrayList को साफ़ करें और इसे क्रमबद्ध सूची के साथ फिर से भरें।

मैं दृढ़ता से सुझाव देता हूं कि Integer.compare() और Boolean.compare() का उपयोग कर अपने तुलनित्र को अधिक सरल बनाएं।

+2

यह नहीं है भाग्य, 'संग्रह .sort' जावा 8 में कार्यान्वयन बदल गया :) – Tunaki

+0

अजीब। मुझे जावा 8 के स्रोत कोड के मेरे संस्करण में यह परिवर्तन नहीं दिख रहा है। शायद यह बहुत पुराना है। मेरे संस्करण में (1.8.0-बी 132), List.sort() संग्रह संग्रह .sort()। –

+1

आह, यह वास्तव में अजीब है।[Grepcode] (http://grepcode.com/file/repository.grepcode.com/java/root/jdk/openjdk/8u40-b25/java/util/Collections.java#Collections.sort%28java.util.List% 2Cjava.util.Comparator% 29) यद्यपि परिवर्तन दिखाता है। – Tunaki

1

जावा 8 में Collections.sort(List, Comparator) के कार्यान्वयन को अब new sort method in the List interface पर रीडायरेक्ट कर दिया गया है। कि sort विधि के डिफ़ॉल्ट कार्यान्वयन पिछले व्यवहार (यानी List.listIterator() का उपयोग कर, जो अभी भी एक UnsupportedOperationException साथ विफल हो जाएगा) हो रहा है, लेकिन स्पष्ट रूप से CopyOnWriteArrayList जो एक Iterator उपयोग नहीं करता है एक अलग संस्करण प्रदान करता है:

public void sort(Comparator<? super E> c) { 
    final ReentrantLock lock = this.lock; 
    lock.lock(); 
    try { 
     Object[] elements = getArray(); 
     Object[] newElements = Arrays.copyOf(elements, elements.length); 
     @SuppressWarnings("unchecked") E[] es = (E[])newElements; 
     Arrays.sort(es, c); 
     setArray(newElements); 
    } finally { 
     lock.unlock(); 
    } 
} 
संबंधित मुद्दे

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