Javaの配列型には、大きく固定長配列と可変長配列の2つがあり、Vectorは動的に要素を増やせる可変長配列にあたります。この記事では、JavaのVectorクラスを使って任意の要素数をもつ可変長配列を作る方法を解説します。
固定長配列と可変長配列
まずは、固定長配列と可変長配列の違いを見ていきましょう。
固定長配列は、宣言時のデータ型とその個数を決定しなければならず、その後に配列のサイズを変更出来ません。
一方でVectorやArrayListのようなクラスは可変長配列となり、要素を追加すると動的に配列のサイズも変更され、基本的には要素数に上限はなく格納できます。
先述のとおり、Vectorクラスは可変長配列に分類されるクラスで、Javaの当初のバージョンから使える歴史が長いコレクションクラスです。
Vectorの使い方
ではVectorクラスを使って要素の追加や削除などを行う基本的な操作を見ていきましょう。
要素の追加
要素の追加をするには、addメソッドを使用します。addメソッドは引数で指定した値を、現在の要素の末尾に追加します。
import java.util.Vector;
public class Main {
public static void main(String[] args) {
// 空のVectorインスタンスを生成
Vector<String> vec = new Vector<>();
vec.add("Apple");
vec.add("Melon");
vec.add("Peach");
vec.add("Orange");
System.out.println(vec);
}
}
実行結果
---------------
[Apple, Melon, Peach, Orange]
要素の削除
要素を削除をする場合は、removeメソッドを使用します。removeメソッドは引数で削除したい要素のインデックスを指定して要素を削除します。
Vector<String> vec = new Vector<>();
vec.add("Apple");
vec.add("Melon");
//2番目の要素を削除
vec.remove(1);
System.out.println(vec);
実行結果
---------------
[Apple]
removeメソッドの引数に、配列に存在しないインデックスを指定するとjava.lang.IndexOutOfBoundsException例外が発生します。
Vector<String> vec = new Vector<>();
vec.add("Apple");
vec.add("Melon");
//5番目の要素を削除(存在しない要素インデックス)
vec.remove(5);
System.out.println(vec);
実行結果
---------------
java.lang.ArrayIndexOutOfBoundsException: Array index out of range: 5
配列の要素数を取得
現在の配列の要素数を取得する場合はsizeメソッドを使います。
Vector<String> vec = new Vector<>();
vec.add("Apple");
vec.add("Melon");
System.out.println(vec.size()); //結果は「2」と表示される
要素の取得
追加した要素から値を取得する場合はgetメソッドを使用します。getメソッドは引数で値を取得したい要素のインデックスを指定して、その位置にある要素の値を取得します。
Vector<String> vec = new Vector<>();
vec.add("Apple");
vec.add("Melon");
System.out.println(vec.get(1)); //「Melon」が表示される
Vectorの要素数で繰り返し
Vectorオブジェクトに格納された要素の数だけ、繰り返し処理をする場合は、elements()メソッドで繰り返し用の反復子を取得して、while等の構文を用いて繰り返し処理をします。
実際に、Vectorのすべての要素を繰り返すサンプルコードを見てみましょう。
Vector<String> vec = new Vector<>();
vec.add("Apple");
vec.add("Melon");
Enumeration<String> e = vec.elements();
while(e.hasMoreElements()) {
String val = e.nextElement();
System.out.println(val);
}
実行結果
---------------
Apple
Melon
ArrayListとVector
Javaの可変長配列には、Vectorの他にもArrayListクラスなどが存在し、Javaの世界では一般的にArrayListがよく用いられ、実はVectorはあまり使われていません。
どちらも要素の追加、削除が行えて、基本的には同じような機能やメソッドを提供しています。違いとしては、Vectorのget, addなどのメソッドには、Psynchronized`キーワードが付いているため、スレッド間で同時アクセスができないように排他制御(スレッドセーフ)がかけられています。
マルチスレッド処理で、1つのVectorオブジェクトに同時にアクセスするようなケースでは、synchronizedによる同期が役に立ちますが、基本的に必要なケースは少なく、逆に同期のための制御がオーバーヘッドになり、ArrayListよりも性能が悪いと言われ、実際の開発の現場でもあまり使われていません。
ArrayListとVectorの性能比較
Vectorはスレッドセーフなので遅いと言うことは分かりました。
では、実際にArrayListとVectorでどの程度、性能に差が発生するのか実験してみましょう。
次のサンプルコードは、100万個の要素を追加する処理をArrayListとVectorでそれぞれ実行し、その処理時間を測定するコードです。
ArrayList
long startTime = System.currentTimeMillis();
//100万個の要素をVectorに追加
ArrayList<String> vec = new ArrayList<>();
for (int i = 0; i < 5000000; i++) {
vec.add("Item" + i);
}
long endTime = System.currentTimeMillis();
System.out.println("処理時間:" + (endTime - startTime) + " ms");for
Vector
long startTime = System.currentTimeMillis();
//100万個の要素をVectorに追加
Vector<String> vec = new Vector<>();
for (int i = 0; i < 5000000; i++) {
vec.add("Item" + i);
}
long endTime = System.currentTimeMillis();
System.out.println("処理時間:" + (endTime - startTime) + " ms");
結果は次の通りとなりました。
- ArrayList:898 ms
- Vector:1036 ms
今回の実験結果からも、ArrayListの方が性能が優れてい結果になりました。
スレッドセーフならCollections.synchronizedList
Vectorはスレッドセーフであるため、スレッド間て配列を共有するケースでは、ArrayListよりもVectorを選択するのが正しいという考えに行き着くと思います。
しかし、公式ドキュメントでも説明がありますが、VectorはJava 1.0からあるレガシーなクラスであるため、使用については推奨されておらずスレッドセーフなArrayListが生成できる、Collections.synchronizedListメソッドの使用が推奨されています。
List list = Collections.synchronizedList(new ArrayList());
まとめ
JavaのVectorの使い方や、Vectorはレガシーなクラスであるため、使用が推奨されていないことについて解説してきました。
Javaは歴史が長いため、同じような機能をもつクラスがいくつかあり、古いクラスは非推奨となることがあるため、クラスを使用する時は、推奨されているクラスであるかを確認しましょう。
メモリの容量が少なく、配列に大量の要素を入れられると困る場合は、Capacityなどのオプションを指定して格納できる要素数に上限値を設定することも可能です。