禁用Java列表中的可变性
在不再需要变异的时候,最好将Java的List接口的对象转换为不可变的等价物。也就是说,客户机可以调用使列表不可变的禁用Java列表中的可变性,java,list,immutability,Java,List,Immutability,在不再需要变异的时候,最好将Java的List接口的对象转换为不可变的等价物。也就是说,客户机可以调用使列表不可变的freeze方法。对我来说,最直接的好处是线程安全,而无需深度复制的内存开销。(编辑:如果人们认为所有线程都能负担得起一个额外的不可变副本,那么他们是正确的。) 是否有提供此类功能的第三方接口或类?如何?尝试使用CopyOnWriteArrayList public class FreezingList<E> implements List<E> {
freeze
方法。对我来说,最直接的好处是线程安全,而无需深度复制的内存开销。(编辑:如果人们认为所有线程都能负担得起一个额外的不可变副本,那么他们是正确的。)
是否有提供此类功能的第三方接口或类?如何?尝试使用
CopyOnWriteArrayList
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的行为与ArrayList
类的行为非常相似,只是当列表
修改后,将创建新数组并丢弃旧数组,而不是修改基础数组。这
这意味着当调用方获取迭代器(即copyOnWriteArrayListRef.iterator())时,该迭代器在内部
保存对基础CopyOnWriteArrayList对象数组的引用,该数组是不可变的,因此可以
用于遍历,无需在列表copyOnWriteArrayListRef上同步或需要
clone()遍历前的copyOnWriteArrayListRef列表(即,没有并发修改的风险)和
还提供了更好的性能。有一个类作为Guava库的一部分。您可以使用copyOf
方法从现有的Iterable
创建一个ImmutableList
,例如
List immutableList=immutableList.copyOf(List)代码>直接使用集合。如果客户端仍有对原始可变列表的引用,则不可修改列表是不够的
我将创建一个委托列表实现,其中包含对原始可变列表(委托)的内部引用,并将所有方法调用转发给它。手工编写这样的代码是一个很好的例子,但是Eclipse可以自动为您生成这样的代码
然后在调用freeze
方法时,我将使用集合包装原始列表。unmodifiableList
,这确保将来对FreezingList
的所有方法调用仅通过unmodifible视图转到原始委托
为了使事情更安全,但更不灵活,您可以更改以下构造函数,并在内部实例化列表(例如作为ArrayList
),而不是将原始列表传递给它(仍然可以将原始可变列表的引用留给客户端)
公共类FreezingList实现列表{
//您委派给的原始列表(委派)
私人名单;
私有布尔冻结=假;
公共免费英语(列表){
this.list=列表;
}
公众假期冻结{
如果(!冻结){
列表=集合。不可修改列表(列表);
冻结=真实;
}
}
//所有授权方法如下:
公共整数大小(){
返回list.size();
}
公共E-get(int索引){
返回列表。获取(索引);
}
//等等等等。
}
你是说其中一个吗。您可以构建自己的列表(作为一种策略),当调用freeze方法时,您可以将内部列表更改为不可变列表。