代码之家  ›  专栏  ›  技术社区  ›  Miserable Variable

如何创建深度不可修改的集合?

  •  14
  • Miserable Variable  · 技术社区  · 16 年前

    在从getter方法返回集合字段之前,我通常使其不可修改:

    private List<X> _xs;
    ....
    List<X> getXs(){
      return Collections.unmodifiableList(_xs);
    }
    

    private List<List<Y>> _yLists;
    .....
    List<List<Y>> getYLists() {
      return Collections.unmodifiableList(_yLists);
    }
    

    当然,上面的问题是,尽管客户端无法修改列表列表,但它可以从嵌入的列表中添加/删除Y对象。

    有什么想法吗?

    6 回复  |  直到 16 年前
        1
  •  7
  •   Miserable Variable    16 年前

    我能想到的最好的用途 ForwardingList from Google Collections . 欢迎评论。

    private static <T> List<List<T>> unmodifiableList2(final List<List<T>> input) {
        return Collections.unmodifiableList(new ForwardingList<List<T>>() {
            @Override protected List<List<T>> delegate() {
                return Collections.unmodifiableList(input);
            }
            @Override public List<T> get(int index) {
                return Collections.unmodifiableList(delegate().get(index));
            }
        });
    }
    
        2
  •  3
  •   Chii    16 年前

    我也有兴趣知道任何优雅的解决方案。

        4
  •  0
  •   iny    16 年前

    如果您查看Collections.unmodifiable*(…)方法的实现,您可以看到它们只是包装集合。以同样的方式进行深层次的实用程序应该是可行的。

    这样做的缺点是,它会向集合访问添加额外的方法调用,从而影响性能。

        5
  •  0
  •   TREE    16 年前

    如果这是一种相当常用的数据结构,另一种选择是使访问它的API更具体,以便您对特定调用有更详细的控制。编写自己的列表实现,如上所述 实现这一点的方法,但如果您可以缩小对特定用例的调用范围,那么您可以公开特定的访问API,而不是列表接口。

        6
  •  0
  •   Ludvig W    7 年前

    如果有人感兴趣,这里有一个简单的解决方案:

        public List<List<Double>> toUnmodifiable(List<List<Double>> nestedList) {
            List<List<Double>> listWithUnmodifiableLists = new ArrayList<>();
                for (List<Double> list : nestedList) {              
                    listWithUnmodifiableLists
                        .add(Collections.unmodifiableList(list));
                }
            return Collections.unmodifiableList(listWithUnmodifiableLists);
        }
    

    我个人发现,在Android中使用GSON实现用于解析的类时,这很有用,因为修改响应(在本例中为反序列化json)是没有意义的,我使用此方法作为使用getter公开列表的方法,并确保列表不会被修改。