2017-06-03 24 views
1

次のプログラムを実行すると、実行に約7〜8分かかりました。私はこのプログラムが実行するのに時間がかかりすぎるので、どこで間違っているのか本当に分かりません。CopyOnWriteArraySetが遅すぎる

public class Test { 
      public static void main(String[] args) { 
      final Integer[] a= new Integer[1000000]; 
      for (int i=0; i < a.length; i++) { 
       a[i] = i; 
      } 
      final List<Integer> source = Arrays.asList(a); 
      final Set<Integer> set = new CopyOnWriteArraySet<Integer>(source); 
     } 
    } 

なぜこのプログラムが遅いのですか?

私のマシンは4ギガバイトRAM

+0

ドキュメントによれば、CopyOnWriteArraysSetはCopyOnWriteArraysListによってサポートされており、通常はセットサイズが小さく留まるアプリケーションに最適です*。 1,000,000人は小さくない。操作はO(n^2)です。 –

+0

@Siguzaこれは本当に問題ではありません。それはまったく時間がかからない。 –

答えて

6

とコアI7である私がテストしていると確かにコンストラクタに提供さ1つの000 000要素のリストと、それは(7分)楽しい時間を要します。
JDK-8005953 - CopyOnWriteArraySet copy constructor is unusable for large collections

問題がCopyOnWriteArraySetコンストラクタによって呼び出さCopyOnWriteArrayList#addAllAbsent()方法によって引き起こす:

それは2013年1月9日オープンJDKで参照さの問題です。問題の

エキス:

CopyOnWriteArraySetのコピーコンストラクタは、大規模な コレクションには遅すぎます。それはあなたが読むことができ、解像度のステータスとして

...コピーするコレクション内だけで 100万のエントリを持つ開発者のラップトップ上で10分以上かかる:は修正されません。
そして、あなたに最後のメッセージを読むことができます:

をaddAllAbsentはより速く、より大きな入力に対して行うことができますが、それは小さなサイズの パフォーマンスに影響を与えるでしょう。そして、 CopyOnWriteXXXクラスは、小さな サイズのコレクションに適していることが記録されています。

CopyOnWriteArraySet javadocが実際にこの点を指定:

それはサイズが一般的に 小さな、読み取り専用の操作が大幅に変更操作を上回って、そして あなたは、干渉を防ぐために必要な滞在しているアプリケーションに最適ですトラバーサル中のスレッド間で

+0

'addAllAbsent()'を見ると、重複を含む可能性のある入力コレクションを一意のアイテムのセットに変換するコストがかかるようです。既存のセットから構築するための特殊なケースではないようです。 –