4

假设我们有一个List<List<String>>并且想让它完全不可修改。仅仅将它传递给 aCollection.unmodifiableList是不够的,因为仍然可以修改内部列表。

我会采用以下方法:

List<List<String>> someList;

使其不可修改:

List<List<String>> tempList = new ArrayList<>();
for(List<String> strList : someList) {
    tempList.add(Collections.unmodifiableList(strList));
}
List<List<String>> safeList = Collections.unmodifiableList(tempList);

这种方法好吗?

4

4 回答 4

1

下面的代码应该做: -

            List<List<String>> tempList = new ArrayList<>();
            for(List<String> strList : someList) {
                tempList.add(new ArrayList<>(strList));
            }
            List<List<String>> safeList = Collections.unmodifiableList(tempList);

这是对此的测试:-

List<List<String>> someList = new ArrayList<>();

        List<String> l1 = new ArrayList<String>();
        List<String> l2 = new ArrayList<String>();

        l1.add("STR1");
        l1.add("STR2");
        l1.add("STR3");

        l2.add("STR4");
        l2.add("STR5");
        l2.add("STR6");

        someList.add(l1);
        someList.add(l2);

        List<List<String>> tempList = new ArrayList<>();
        for(List<String> strList : someList) {
            tempList.add(new ArrayList<>(strList));
        }
        List<List<String>> safeList = Collections.unmodifiableList(tempList);

        l1.add("STR7"); // The inner list reference is modified this doesnot cause the safelist internal structure to get changed

        for(List<String> safeInnerList : safeList) {
            System.out.println(safeInnerList);
        }
于 2014-08-11T17:35:23.427 回答
1

我觉得它不起作用:-

    List<List<String>> someList = new ArrayList<>();

            List<String> l1 = new ArrayList<String>();
            List<String> l2 = new ArrayList<String>();

            l1.add("STR1");
            l1.add("STR2");
            l1.add("STR3");

            l2.add("STR4");
            l2.add("STR5");
            l2.add("STR6");

            someList.add(l1);
            someList.add(l2);

            List<List<String>> tempList = new ArrayList<>();
            for(List<String> strList : someList) {
                tempList.add(Collections.unmodifiableList(strList));
            }
            List<List<String>> safeList = Collections.unmodifiableList(tempList);

            l1.add("STR7"); // The inner list reference is modified which causes the 
safelist internal structure to get changed

            for(List<String> safeInnerList : safeList) {
                System.out.println(safeInnerList);

            }
于 2014-08-11T17:24:43.183 回答
1

只要您不保留对原始可修改列表的引用,这种方法就应该有效。这样的引用可以修改由不可修改列表包裹的列表。

于 2014-08-11T17:12:51.533 回答
1

实现不变性的方法是创建防御性副本。

数据在

每当将可变对象传递给您的方法时,您都会创建它的深层副本。如果您想要最大的安全性,这应该是您做的第一件事,甚至在您检查有效性之前。

将列表包装成 aCollections.unmodifiableList()在这里不起作用,因为不能保证底层列表不会被第三方修改。换句话说,您无法控制该实例。

创建列表的不可变副本的一个好方法是使用 Google Guava 的ImmutableList.copyOf()方法,但请记住,您需要一个深层副本,因此您需要在主列表中创建列表的不可变副本。

数据输出

每当您返回一个值时,您都会制作另一个防御性副本,以便对返回对象的更改不会反射回来。在这里,您可以在列表中使用不可修改的包装器(例如ImmutableList.of()),因为您拥有对原始列表的唯一引用。

如果您同时执行这两种操作(输入时复制,输出时复制/换行),您的代码将是安全且正确的。任何其他解决方案都不能给出这样的一般保证,您的代码可能不正确,也可能很多不正确。

于 2014-08-11T17:16:52.503 回答