- Contents -
Collections::unmodifiableXXX
Map、Set、ListなどのCollectionを、変更不可なものとして扱うのに
Collections::unmodifiableXXX を使う方法があります。
add, put, remove などの、コレクションの追加、削除などを抑制する事ができます。
Collections::UnmodifiableCollection
Collections::UnmodifiableSet
Collections::UnmodifiableSortedSet
Collections::UnmodifiableNavigableSet
Collections::UnmodifiableList
Collections::UnmodifiableRandomAccessList
Collections::UnmodifiableMap
Collections::UnmodifiableSortedMap
Collections::UnmodifiableNavigableMap
unmodifiable〜 は、これだけありますが、このあたりを使うだけで充分でしょう。
Collections::UnmodifiableSet
Collections::UnmodifiableList
Collections::UnmodifiableMap
使い方
元々の、コレクションを下記のように Collections.unmodifiableList(xxx)
を通す事で、
unmodifiableなコレクションにラップして返してくれます。
unmodifiableなコレクションでは、add, remove, put など、コレクションに変更を加える操作が禁止されます。
もしコールすると、UnsupportedOperationException という例外が投げられます。
// List<Hoge> hogeList があるとして
List<Hoge> unmodifiableHogeList = Collections.unmodifiableList(hogeList);
// 参照して使う分には、普通に使える
Hoge hoge = unmodifiableHogeList.get(0);
// remove, add など、コレクションを変更するメソッドはエラーが発生する。
unmodifiableHogeList.remove(0);
コレクションはラップされている
unmodifiable系のコレクションは、コレクションコピーを作成しているわけではなく、
元々のコレクションのインスタンスをメンバ変数に保持して、ラップしてるだけです。
UnmodifiableListの実装
static class UnmodifiableList<E> extends UnmodifiableCollection<E>
implements List<E> {
private static final long serialVersionUID = -283967356065247728L;
final List<? extends E> list;
UnmodifiableList(List<? extends E> list) {
super(list);
this.list = list;
}
public boolean equals(Object o) {return o == this || list.equals(o);}
public int hashCode() {return list.hashCode();}
public E get(int index) {return list.get(index);}
public E set(int index, E element) {
throw new UnsupportedOperationException();
}
public void add(int index, E element) {
throw new UnsupportedOperationException();
}
public E remove(int index) {
throw new UnsupportedOperationException();
}
public int indexOf(Object o) {return list.indexOf(o);}
public int lastIndexOf(Object o) {return list.lastIndexOf(o);}
public boolean addAll(int index, Collection<? extends E> c) {
.
.
コレクションコピーよりスマート
コレクション改変を許容しない場合に、外部にコレクションのインスタンスを渡す場合に、
こんな感じで、コレクションコピーを作成していましたが、
public List<Hoge> hogeList(){
return new ArrayList<>(_hogeList);
}
Collections.unmodifiableXXXを使う方が、スマートでしょう。
public List<Hoge> hogeList(){
return Collections.unmodifiableList(_hogeList);
}
コレクションをコピーしている訳ではなくラップしてるだけなので、
無駄なコピーが発生しなくて改変される心配もなくなります。
再帰的にunmodifiableされる訳ではない。
Map構造などで、Map<Integer, Map<Integer, String>>
のような
Mapの値が更にMapになっているようなコレクションの場合、
unmodifiableMapを使っても、内側のMapまでがunmodifiableになる訳ではないのでお間違いなく。
二重Mapをつかった、動作サンプルです。
Map<Integer, Map<Integer, String>> map = new HashMap<>();
// 適当に要素を追加
map.put(1, new HashMap<>());
map.get(1).put(1, "1-1");
map.get(1).put(2, "1-2");
map.get(1).put(3, "1-3");
map.put(2, new HashMap<>());
map.get(2).put(1, "2-1");
map.get(2).put(2, "2-2");
map.get(2).put(3, "2-3");
// unmodifiableMap を生成
Map<Integer, Map<Integer, String>> unmodifiableMap = Collections.unmodifiableMap(map);
// ここはもちろん例外が発生する。
unmodifiableMap.remove(1);
// ここは内部のMapなので、操作できる。
unmodifiableMap.get(1).remove(1);