【问题标题】:How to return a constant collection如何返回一个常量集合
【发布时间】:2013-11-15 21:05:09
【问题描述】:

在 java 中有没有办法返回对类集合的引用,而我不能更改它也不能更改其元素的数据?

那么,如果我有一个地图Map<Integer, Set<String>>,没有任何主体可以获取对设置值的引用并向其中添加元素?

【问题讨论】:

  • 你可以在交给别人之前克隆它,所以即使他改变它也不会影响你的程序
  • 但如果它真的很大,那就太多了

标签: java


【解决方案1】:

保证Map 中的所有对象 不能被修改的唯一方法,即使Map 本身是不可修改的,也就是让对象自己不可变

unmodifiableMap() 方法保证Map 不能被修改,但它根本不保证它包含的对象。查看this 了解如何使对象不可变。举个具体的例子,看看String 类是如何工作的:你不能修改字符串中的字符,所有可以改变字符串的方法(例如:toUpperCase())都返回一个new 字符串。这就是您希望 Map 中的对象的行为。

鉴于问题中的地图包含 Set<String> 作为其值,然后在集合上使用Collections.unmodifiableSet()之前将它们添加到地图将使它们不可变,因为String,如如上所述,已经是不可变的。

【讨论】:

    【解决方案2】:

    您可以使用Collections.unmodifiableMap 获取无法修改的地图视图。

    每种类型的集合都有不同的方法:

    • unmodifiableCollection 返回通用集合的不可修改视图
    • unmodifiableSet 返回 Set 的不可修改视图
    • unmodifiableList 返回列表的不可修改视图
    • unmodifiableSortedSet 返回一个不可修改的 SortedSet 视图
    • unmodifiableSortedMap 返回一个不可修改的 SortedMap 视图

    如果项目本身是集合,您可以编写一个递归方法来构造一个新集合,该集合包含原始项目的不可修改视图。

    一般来说,如果您存储在集合中的项目本身可以修改,那么除了制作防御性副本之外,没有什么能阻止您这样做。

    【讨论】:

    • 我使用了它,但它不起作用,我可以获得对地图中某个值的引用并更改其数据。
    • 这是一个完全不同的问题! Unmodifiable 对象的集合与 Unmodifiable 集合完全不同。这个问题的答案是否定的。
    • @Doggynub 除了将Map 装饰为不可修改之外,您还应该将Sets 元素也装饰为不可修改。如果你想用自己的类来做,你必须确保你的类也是不可变的。
    • 是的,我的对象是不可变的,但它们包含在集合中,那么递归函数怎么样?
    • 看到您只有一层嵌套集合 (Map<Integer,Set<String>>),您实际上并不需要递归函数。只需构建一个新映射并遍历现有映射的键和值,对每一对执行 newMap.put(key, Collections.unmodifiableSet(value))
    【解决方案3】:

    通过您自己提供的方法调解对外部集合 (Map) 的访问,可能最容易实现您的目标。然后,您可以在通过 Collections.unmodifiableSet() 传递适当的 Set 对象后返回它。

    由于String 是不可变的,调用者在这之后真的没有什么可以改变的了。

    除此之外,您还必须构建一个新的Map,其中包含所有通过Collections.unmodifiableSet() 传递的集合,然后通过Collections.unmodifiableMap() 传递它。但是,这可能是一个好主意,也可能不是一个好主意,具体取决于您的收藏有多大。

    【讨论】:

    • 有没有一种方法可以让该集合也保持不变而无需复制新内容?
    • 这只会复制地图元素而不是设置的元素吗?该集合只会从新地图中的不可变视图返回?
    • 正确,这是一个浅拷贝(这就是你希望它们不可变的真正原因)。我想既然Map 被复制了,之后就没有必要让它不可修改了。至于直接实现目标的方式......我不知道任何内置方式。我认为你需要做一些事情,比如推出你自己的不可修改的地图实现,通过unmodifiableSet()传递返回的值。
    【解决方案4】:

    地图:

    Map<Integer, String> myMap =
                Collections.unmodifiableMap(new HashMap<Integer, String>() {
            {
                put(1, "value1");
                put(2, "value2");
                put(3, "value3");
            }
        });
    

    列表:

    List<String> list = Collections.unmodifiableList(new ArrayList<String>() {
            {
                add("value1");
                add("value2");
                add("value3");
            }
        });
    

    设置:

    Set<String> list = Collections.unmodifiableSet(new HashSet<String>() {
            {
                add("value1");
                add("value2");
                add("value3");
            }
        });
    

    【讨论】:

      猜你喜欢
      • 2011-10-02
      • 2013-02-18
      • 1970-01-01
      • 2019-10-08
      • 1970-01-01
      • 2012-08-14
      • 1970-01-01
      • 2020-07-18
      • 2016-07-20
      相关资源
      最近更新 更多