コレクションを活用するためのユーティリティメソッド
■ 同期化
- synchronizedList
- synchronizedMap
public static List synchronizedList(List list)
public static Map synchronizedMap(Map m)
複数のスレッドが同時にコレクションに対して要素の追加や削除などを行うと、コレクションが破壊されてしまう可能性があります。これを防ぐためにはコレクションを同期化する必要があります。しかし同期化にはコストがかかるため、ArrayListなどのクラスは同期化を行っていません。
synchronizedList/synchronizedMapメソッドは引数で指定されたリスト/マップを基にした同期化したリスト/マップを返します。これらのメソッドを使用することで複数のスレッドで使用しても安全なコレクションを作成することができます。
ただし、同期化したリストから得られるIteratorオブジェクトは同期化を行っていません。したがって、複数スレッドでIteratorオブジェクトを使用する場合にはリスト1のようにユーザが同期化をする必要があります。
同期化したマップからkeySetなどで得られるSetオブジェクトは同期化しています。しかし、そのSetオブジェクトから取り出したIteratorオブジェクトはリストと同様に同期化していないので、リストの場合と同様にユーザが同期化を行う必要があります。
List syncList = Collections.synchronizedList(list); synchronized (syncList) { Iterator it = syncList.iterator(); while (it.hasNext()) { Object obj = it.next(); // 何らかの処理 } }
■ 変更不可能化
- unmodifiableList
- unmodifiableMap
public static List unmodifiableList(List list)
public static Map unmodifiableMap(Map m)
引数のリスト/マップを変更ができないリスト/マップに変更します。このメソッドによって得られたリスト/マップはgetメソッドなどは使用できますが、addメソッドなどのコレクションを変更するようなメソッドをコールするとUnsupportedOperationExceptionがスローされます。リスト2でNGになっている操作がこれに相当します。
また、リスト2に示すように変更不可能なリストから得られるIteratorオブジェクトも変更不可能です。同様にマップのkeySetメソッドなどで得られるSetオブジェクトも変更不可能です。
List unmodList = Collections.unmodifiableList(list); Object obj = unmodList.get(i); // OK int size = unmodList.size(i); // OK unmodList.add(value); // NG unmodList.remove(obj); // NG Iterator it = unmodList.iterator(); // OK Object obj = it.next(); // OK it.remove(); // NG
■ リストのソート
- sort
public static void sort(List list)
public static void sort(List list, Comparator comparator)
リストの要素を昇順にマージソートアルゴリズムを使用してソートします。
前者の引数が1つの sort メソッドは、リストの全ての要素がjava.lang.Comparableインタフェースを実装していなくてはいけません。ComparableインタフェースにはcompareToメソッドが定義されており、このメソッドで値の大小を決定します。
もう一方の sort メソッドはjava.util.Comparatorインタフェースを使用します。Comparatorインタフェースのcompareメソッドでリストの要素同士の大小を比較します。
Collections クラスでリストに対する処理を行う sort や rotate などのメソッドで気をつける点として、引数で指定されたリストが変更されてしまうということがあります。もし、リストが変更されたくない場合はあらかじめリストをコピーしておくなどの処置が必要です。
■ リストの検索
- sortbinarySearch
public static int binarySearch(List list, Object key)
public static int binarySearch(List list, Object key, Comparator comparator)
バイナリサーチを使用してリストの要素を検索します。sortメソッドと同様に要素とkeyがComparableインタフェースを実装するか、Comparatorオブジェクトで大小が決められるようにしなくてはなりません。
リスト3にbinarySearchメソッドの使用例を示しました。binarySearchメソッドを使用する場合、事前にリストがソートされている必要があります。リスト3はsortメソッドを使用していますが、sort メソッドの項で説明したように、リストを変更してしまうため変更されたくない場合にはあらかじめコピーを作成し、それに対してソートするようにします。
ListインタフェースにはindexOfメソッドが定義されており、これを利用して要素の検索を行うことができます。しかし、要素数が多くなるとリストの先頭からシーケンシャルに調べていくためパフォーマンスに問題が出てきます。
binarySearchメソッドはバイナリサーチを使用しているので、要素数の増加に対するパフォーマンス劣化が比較的小さいため、要素数が多いときに有効になります。
binarySearchメソッドの戻り値はリストにkeyが含まれていれば、そのインデックスになります。keyが無いときにはリストの中でkeyが挿入されるべきインデックスの1つ前の値をマイナスにした値になります。例えば、リスト[a, c, e, g, k, m]でhを探索するとします。hはgとkの間に挿入され、gのインデックスは3なので、それをマイナスにした値-3が戻り値になります。
List tmpList = new ArrayList(list); Collections.sort(tmpList); int index = Collections.binarySearch(tmpList, key);
(2002.09)