java - 如何使Map的特化变得不可修改?

标签 java generics collections unmodifiable

我目前正在通过一个中型编码示例来刷新我的 Java 知识。我有一个数据结构Map<String, String> ,并通常使用 new LinkedHashMap<>() 对其进行初始化保留插入顺序。我在代码中经常使用它,并且我想摆脱声明重复。在 C++ 中,我会给 map 起别名,但据我所知,在 Java 中没有别名。

所以我想到了像这样子类化泛型的想法:

public class Attributes extends LinkedHashMap<String, String> {

    public Attributes() {
        super();
    }

    public Attributes(Map<? extends String, ? extends String> map) {
        super(map);
    }

}

到目前为止,这看起来不错,但现在我想创建它的不可修改的副本,因为属性应该是不可变/不可修改的数据结构的一部分。在我使用这个之前:

Map<String, String> unmodifiableAttributes = Collections.unmodifiableMap(
        new LinkedHashMap<>(attributes)
);

这不适用于派生类,我尝试过:

Attributes unmodifiableAttributes = Collections.unmodifiableMap(
        new Attributes(attributes)
);

编译器以 Incompatible types 拒绝它。

是否有一种简单的方法来获取此类子类的不可修改(或不可变)副本?还是我的想法完全错误?我不想写一个功能齐全的装饰器,只想写几行代码。

更新

到目前为止,对于我想做的事情似乎没有好的解决方案。我查看了Java Collections类的源代码,有不可修改的映射和类似集合的内部类。它们用于包装输入集合并由相应的静态方法返回。人们可以重新实现这一点,但我认为开销太大。

我们对 LSP 违规进行了更多讨论,而不是原来的问题,这确实也是一个有趣的问题。

最佳答案

您不能使子类 LinkedHashMap 不可修改,因为它会违反里氏可替换性:LinkedHashMap 被记录为可变的,因此所有子类也必须是可变的。

您还有一个额外的问题,即要使 map 不可修改实际上需要做很多工作:您不仅有 putremove 等明显的方法,而且还有诸如 clearputAllputIfAbsentcomputeIfAbsentcomputeIfPresent 等内容。然后你必须担心 View 返回方法:entrySetkeySetvalues都必须返回不可修改的 View 。我确信我错过了几个也需要重写的方法,但我的观点仍然是,使可变映射不可修改并不是微不足道的。

但是,您可以拥有不可修改的 Map 实现。最简单的方法是扩展 AbstractMap ,并委托(delegate)给实际的 LinkedHashMap:

public class Attributes extends AbstractMap<String, String> {
    private final LinkedHashMap<String, String> delegate;

    public Attributes() {
        this(Collections.emptyMap());
    }

    public Attributes(Map<? extends String, ? extends String> map) {
        this.delegate = new LinkedHashMap<>(map);
    }

    // Override the methods you need to, and that are required by AbstractMap.
    // Details of methods to override in AbstractMap are given in Javadoc.
}

但我也会质疑您的 Attributes 类是否真的需要实现像 Map 接口(interface)一样通用的东西 - 如果您需要这种通用性,您可以简单地使用 Map直接。

关于java - 如何使Map的特化变得不可修改?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57740120/

相关文章:

java - CopyOnWriteArrayList 可以与可变对象一起使用吗?

c# - 带可更换元素的 key 系列

java - 使用Java以编程方式读取存储在HDFS中的文本文件的内容

java - 达美航空速度太快了

typescript - 使用 typescript 强制执行参数组合

c# - 使用泛型的新手多态性问题

java - .jar 库中的 Android .jar 库 - 嵌套依赖项

java - 尝试将 Object 转换为 EMF EObject 时出现 ClassCastException?

java - 将 Java 泛型限制为类

java - JPA - SortedSet 需要 OrderBy