【问题标题】:Is it possible to make a modifiable copy of an unmodifiable map?是否可以制作不可修改地图的可修改副本?
【发布时间】:2020-03-20 21:46:57
【问题描述】:

说明:

我的一个问题集提供了测试用例,以检查键入的代码是否正常工作。我不会详细介绍,但基本上这些测试将地图作为输入。我的代码适用于所有测试用例,除了一个:当我查看测试时,我看到输入映射变为不可修改的映射 (Collections.unmodifiableMap(numbers)),而这个不可修改的地图被传递给我写的方法。这是唯一的测试,所以我想知道是否可以复制这个不可修改的地图,以便可以在我的方法中修改它?我必须做的最重要的修改是更新键的值 (map.put(key, map.get(key)-1)。

扩展:

另外一个问题,对于其他数据结构(例如列表或集合)是否有类似的方法?

【问题讨论】:

  • 您可以将不可修改的地图制作成可修改的副本,但任何修改只会影响可修改的副本,不会影响不可修改的原图。
  • 我有点困惑:您的代码正在修改输入并通过所有测试,但随后另一个测试通过了不可修改的输入。那么,您的代码是否应该 修改输入,或者这是一种不需要且未在测试中检查的副作用?
  • 我的代码肯定是要修改输入的(收费公路重建,回溯),所以我认为这只是一个错误。或者有没有办法在不修改输入的情况下解决这个问题?

标签: java data-structures


【解决方案1】:

最简单的方法是创建一个新地图:

final Map<?, ?> unmodifiable = Collections.unmodifiableMap(new HashMap<>());
final Map<?, ?> modifiable = new HashMap<>(unmodifiable);

两个地图都引用了相同的值。

扩展

对于像列表和集合这样的集合,它的工作方式类似。它们通常具有构造函数,您可以将另一个集合传递给它们。

【讨论】:

    【解决方案2】:

    不必创建新的 List 或 Map 来更新其对象的状态。不可修改的是集合,而不是其中的对象。

          List<Foo> mod = IntStream.range(1, 10).mapToObj(Foo::new).collect(
                Collectors.toList());
          List<Foo> unmod = Collections.unmodifiableList(mod);
          // unmod.add(new Foo(20)); <-- can't do this
    
          List<Foo> subList = unmod.subList(2, 4);
          //  subList.remove(0); <-- or this
          Foo f = unmod.get(3); 
          f.v = 99; // <-- but this is allowed
          System.out.println(unmod);
    
    
          class Foo {
              int v;
    
              Foo(int v) {
                  this.v = v;
              }
              public String toString() {
                  return v + "";
              }
           }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2016-04-20
      • 2013-07-27
      • 2015-02-27
      • 2011-10-27
      • 2011-01-28
      • 2012-05-26
      • 1970-01-01
      相关资源
      最近更新 更多