2016-01-16 11 views
8

私は次のコードとJava 8を使用して何の問題もなく、ユーザのリストを並べ替えることができます。なぜCollections.sort(List)はJava 8で動作しますか?CopyOnWriteArrayListでは動作しますが、Java 7では動作しません。

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

は今、私は、Java 7に変更し、私は日食に何のエラーを見ませんでした。しかし今、Java 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

Collections.sortの作業(、Holgerのように)では、Java 7(およびJava 8の初期バージョン)とJava 8u20の間に変更がありました。


のJava 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を取得することによって行われます。 、これは回避策としてのJava 7を使用してコードを実行したときに取得しているエラーを説明する

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.

あなたはthis questionを参照することができます。しかし、CopyOnWriteArrayListlistIterator()方法が返される反復子はset操作をサポートしていないと述べています答えは配列の内容を配列にダンプし、配列をソートして要素をリストに戻すことです。

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

そして、それが正常に動作するように、リスト反復子を使用していません(Javaの8で導入された)新しいメソッドCopyOnWriteArrayList.sort(c)


は、Java 8では、 Collections.sort(list, c)は、実装を変更しました。

2

Collections.sort()のJava 7(およびJava 8の初期バージョン)では、リストイテレータのset()を使用してリストを変更します。しかし、CopyOnWriteArrayListのイテレータは、この操作をサポートしていないと明示的に記述されています。

修正方法? CopyOnWriteArrayListを通常のArrayListまたは配列に変換してソートしてから、CopyOnWriteArrayListをクリアしてソートされたリストでもう一度入力してください。

Integer.compare()Boolean.compare()を使用すると、コンパレータをより簡単にすることを強くお勧めします。

+2

それはないです。それsort方法は(まだUnsupportedOperationExceptionで失敗しList.listIterator()を使用して、すなわち)以前の動作のようですが、CopyOnWriteArrayListが明示的にIteratorを使用していない別のバージョンを提供するデフォルトの実装'Collections.sort'はJava 8の実装を変更しました:) – Tunaki

+0

Strange。 Java 8のソースコードの私のバージョンでは、その変更は見られません。多分古すぎるかもしれません。私のバージョン(1.8.0-b132)では、List.sort()はCollections.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

Java 8では、Collections.sort(List, Comparator)の実装がnew sort method in the List interfaceにリダイレクトされました。

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(); 
    } 
} 
関連する問題