Guava库中有一个ImmutableList类。您可以使用 copyOf 方法从现有的
Iterable 创建一个
ImmutableList ,例如。
List<String> immutableList = ImmutableList.copyOf(list);
如果客户端仍然引用原始可变列表,则直接使用Collections.unmodifiableList
是不够的。
我会创建一个委托列表实现,它将具有对原始可变列表(代理)的内部引用,并将所有方法调用转发给它。手动编写这样的代码很麻烦,但例如Eclipse可以自动生成它。
然后,在调用freeze
方法时,我会使用Collections.unmodifiableList
包装原始列表,以确保将来对FreezingList
的所有方法调用都通过不可修改的视图仅转到原始代理。
为了使事情更安全,但更不灵活,您可以更改以下构造函数,而不是将原始列表传递给它(这仍然可能使客户端引用原始可变列表),在内部实例化列表(例如作为ArrayList
)。
public class FreezingList<E> implements List<E> {
// the original list you delegate to (the delegate)
private List<E> list;
private boolean frozen = false;
public FreezingList(List<E> list) {
this.list = list;
}
public void freeze() {
if (!frozen) {
list = Collections.unmodifiableList(list);
frozen = true;
}
}
// all the delegating methods follow:
public int size() {
return list.size();
}
public E get(int index) {
return list.get(index);
}
// etc. etc.
}
尝试使用CopyOnWriteArrayList
。
CopyOnWriteArrayList的行为类似于ArrayList
类,但在修改列表时,它不会修改底层数组,而是创建一个新数组并且旧数组被丢弃。这意味着当调用者获取迭代器(即copyOnWriteArrayListRef.iterator()),它内部持有对底层CopyOnWriteArrayList对象数组的引用,该数组是不可变的,因此可以进行遍历,无需在列表copyOnWriteArrayListRef上同步或在遍历之前需要clone() copyOnWriteArrayListRef列表(即没有并发修改的风险),并且还提供更好的性能。