Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/349.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
禁用Java列表中的可变性_Java_List_Immutability - Fatal编程技术网

禁用Java列表中的可变性

禁用Java列表中的可变性,java,list,immutability,Java,List,Immutability,在不再需要变异的时候,最好将Java的List接口的对象转换为不可变的等价物。也就是说,客户机可以调用使列表不可变的freeze方法。对我来说,最直接的好处是线程安全,而无需深度复制的内存开销。(编辑:如果人们认为所有线程都能负担得起一个额外的不可变副本,那么他们是正确的。) 是否有提供此类功能的第三方接口或类?如何?尝试使用CopyOnWriteArrayList public class FreezingList<E> implements List<E> {

在不再需要变异的时候,最好将Java的List接口的对象转换为不可变的等价物。也就是说,客户机可以调用使列表不可变的
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方法时,您可以将内部列表更改为不可变列表。