回答:
Vector
個々の操作ごとに同期します。それはあなたがしたいことはほとんど決してありません。
通常は、一連の操作全体を同期させます。個々の操作の同期は安全性が低くなります(Vector
たとえば、を反復する場合でも、他のユーザーが同時にコレクションを変更するのを防ぐためにロックを解除する必要があります。これによりConcurrentModificationException
、反復スレッドでが発生します)が遅くなります(一度だけで十分なときに、なぜロックを繰り返し解除するのですか?
もちろん、必要がない場合でもロックのオーバーヘッドがあります。
基本的に、これはほとんどの状況での同期に対する非常に欠陥のあるアプローチです。以下のようミスターブライアンヘンクは指摘し、あなたが電話を使用してコレクションを飾ることができるようなCollections.synchronizedList
-という事実Vector
コンバイン両方の「すべての操作を同期」ビットと「サイズ変更された配列」コレクションの実装は貧弱な設計の別の例です。装飾アプローチは、問題をより明確に分離します。
Stack
同等-私は見たいDeque
/ ArrayDeque
で開始します。
Vectorは1.0の一部でした。元の実装には2つの欠点がありました。
1.ネーミング:ベクトルは実際には配列としてアクセスできる単なるリストなので、呼び出される必要がありますArrayList
(これはのJava 1.2コレクションの置き換えですVector
)。
2.同時実行性:すべてのget()
、set()
メソッドはsynchronized
同期を細かく制御することはできません。
そこの間に大きな違いはないArrayList
とはVector
、しかし、あなたは使用する必要がありますArrayList
。
APIドキュメントから。
Java 2プラットフォームv1.2以降、このクラスはListインターフェースを実装するために改良され、Java Collections Frameworkのメンバーになりました。新しいコレクションの実装とは異なり、Vectorは同期されます。
ArrayList
、LinkedList
インターフェイスを実装するすべては、など、List
あなたが利用したいのであれば、List
基本となる実装が実際にあなただけ取ることができているかを知ることなく、方法をList
など、メソッドのパラメータと同じでの実装に適用されますMap
等々。一方、C ++にはstd::array
クラスがあり、これはCスタイルの静的長さ配列のテンプレートベースの置き換えにすぎません。
Vectorの使用に関する既述の回答に加えて、VectorにはListインターフェースとは異なる列挙および要素の取得に関するメソッドの束もあり、開発者(特に1.2より前にJavaを学んだ人)は、それらがコード。列挙型の方が高速ですが、反復中にコレクションが変更されたかどうかをチェックしないため、問題が発生する可能性があります。また、同期のためにベクターが選択されている可能性があるため、複数のスレッドからのアテンダントアクセスで、これは特に悪質な問題になります。これらのメソッドを使用すると、多くのコードがVectorに結合されるため、別のList実装に簡単に置き換えることはできません。
でsynchronizedCollection / Listメソッドを使用してjava.util.Collection
、非スレッドセーフコレクションからスレッドセーフコレクションを取得できます。
java.util.Stack
の同期オーバーヘッドを継承します java.util.Vector
、通常は正当化されません。
それはそれよりもはるかに多くを継承します。これjava.util.Stack extends java.util.Vector
がオブジェクト指向設計の誤りです。純粋主義者は、スタックに従来から関連付けられていた操作(つまり、プッシュ、ポップ、ピーク、サイズ)以外にも多くのメソッドを提供していることに気付くでしょう。それは何をすることも可能ですsearch
、elementAt
、setElementAt
、remove
、および他の多くのランダム・アクセス・オペレーション。の非スタック操作の使用を控えるのは、基本的にユーザー次第ですStack
。
これらの性能とOOPの設計上の理由から、のJavaDocをjava.util.Stack
推奨していますArrayDeque
は自然な代替としてしています。(両端キューはスタック以上のものですが、少なくともすべてにランダムアクセスを提供するのではなく、両端を操作することに制限されています。)