1. 概要

このチュートリアルでは、ArrayListクラスとVectorクラスの違いに焦点を当てます。 これらは両方ともJavaコレクションフレームワークに属し、java.util.Listインターフェースを実装します。

ただし、これらのクラスには、実装に大きな違いがあります

2. 何が違うの?

クイックスタートとして、 ArrayListとVectorの主な違いを紹介しましょう。次に、いくつかのポイントについて詳しく説明します。

  • 同期–これら2つの最初の大きな違い。 Vector は同期されていますが、ArrayListは同期されていません。
  • サイズの拡大– 2つの違いは、容量に達したときにサイズを変更する方法です。 ベクトルはそのサイズを2倍にします。 対照的に、ArrayListはその長さの半分だけ増加します
  • 反復–そして Vectorは、イテレータと列挙を使用して要素をトラバースできます。 一方で、 配列リストしか使用できませんイテレータ
  • パフォーマンス–主に同期のため、 Vector の操作は、ArrayListと比較すると遅くなります。
  • フレームワーク–また、 ArrayList はCollectionsフレームワークの一部であり、JDK1.2で導入されました。 一方、 Vector は、以前のバージョンのJavaにレガシークラスとして存在します。

3. ベクトル

ArrayList、に関する拡張ガイドがすでにあるため、ここではそのAPIと機能については説明しません。 一方、Vectorに関するいくつかのコアの詳細を示します。

簡単に言えば、Vectorはサイズ変更可能な配列です。 要素を追加または削除すると、拡大および縮小する可能性があります。

通常の方法でベクトルを作成できます。

Vector<String> vector = new Vector<>();

デフォルトのコンストラクターは、初期容量が10の空のVectorを作成します。

いくつかの値を追加しましょう:

vector.add("baeldung");
vector.add("Vector");
vector.add("example");

最後に、 Iterator インターフェースを使用して、値を繰り返し処理してみましょう。

Iterator<String> iterator = vector.iterator();
while (iterator.hasNext()) {
    String element = iterator.next();
    // ...
}

または、列挙を使用してVectorをトラバースできます。

Enumeration e = vector.elements();
while(e.hasMoreElements()) {
    String element = e.nextElement();
    // ... 
}

それでは、それらの独自の機能のいくつかをさらに詳しく見ていきましょう。

4. 並行性

ArrayListVectorは同時実行戦略が異なることはすでに説明しましたが、詳しく見ていきましょう。 Vectorのメソッドのシグネチャに飛び込むと、それぞれに同期されたキーワードがあることがわかります。

public synchronized E get(int index)

簡単に言えば、これは、一度に1つのスレッドのみが特定のベクトルにアクセスできることを意味します

ただし、実際には、この操作レベルの同期は、複合操作用の独自の同期ととにかくオーバーレイする必要があります。

したがって、対照的に、ArrayListは別のアプローチを取ります。 そのメソッドは同期されておらず同期されておらず、その懸念は並行性に専念するクラスに分けられています。

たとえば、CopyOnWriteArrayListまたはCollections.synchronizedListを使用して、Vectorと同様の効果を得ることができます。

vector.get(1); // synchronized
Collections.synchronizedList(arrayList).get(1); // also synchronized

5. パフォーマンス

すでに上で説明したように、ベクトルは同期されているため、パフォーマンスに直接影響します

Vector操作とArrayList操作のパフォーマンスの違いを確認するために、簡単なJMHベンチマークテストを作成してみましょう。

過去に、私たちは見てきました ArrayListの操作の時間計算量 、では、のテストケースを追加しましょうベクター。

最初の get()メソッドをテストしてみましょう。

@Benchmark
public Employee testGet(ArrayListBenchmark.MyState state) {
    return state.employeeList.get(state.employeeIndex);
}

@Benchmark
public Employee testVectorGet(ArrayListBenchmark.MyState state) {
    return state.employeeVector.get(state.employeeIndex);
}

3つのスレッドと10回のウォームアップ反復を使用するようにJMHを構成します。

そして、ナノ秒レベルでの操作ごとの平均時間について報告しましょう。

Benchmark                         Mode  Cnt   Score   Error  Units
ArrayListBenchmark.testGet        avgt   20   9.786 ± 1.358  ns/op
ArrayListBenchmark.testVectorGet  avgt   20  37.074 ± 3.469  ns/op

ArrayList#getはVector#getの約3倍の速度で動作することがわかります。

それでは、 contains()操作の結果を比較してみましょう。

@Benchmark
public boolean testContains(ArrayListBenchmark.MyState state) {
    return state.employeeList.contains(state.employee);
}

@Benchmark
public boolean testContainsVector(ArrayListBenchmark.MyState state) {
    return state.employeeVector.contains(state.employee);
}

そして、結果を印刷します。

Benchmark                              Mode  Cnt  Score   Error  Units
ArrayListBenchmark.testContains        avgt   20  8.665 ± 1.159  ns/op
ArrayListBenchmark.testContainsVector  avgt   20  36.513 ± 1.266  ns/op

ご覧のとおり、 contains()操作の場合、Vectorのパフォーマンス時間はArrayListよりもはるかに長くなります。

6. 概要

この記事では、JavaのVectorクラスとArrayListクラスの違いについて説明しました。 さらに、Vector機能についても詳しく説明しました。

いつものように、この記事の完全なコードは、GitHubから入手できます。