Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/394.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 为什么我们有不变的空映射?_Java_Collections_Map_Immutability - Fatal编程技术网

Java 为什么我们有不变的空映射?

Java 为什么我们有不变的空映射?,java,collections,map,immutability,Java,Collections,Map,Immutability,我在线程“main”java.lang.UnsupportedOperationException中得到异常 因为集合不可变不支持修改。那么这种数据结构有什么用呢 此类类和实用程序方法有什么用途 如果您正在返回一个映射结果,它通常是不可变的。。。例如,您可以创建一个不可变的映射来包装您自己的“真实”数据,而无需创建完整副本,或者信任调用方不会对其进行变异 此外,如果返回的是空的映射结果,则不必每次都创建一个新对象是很方便的-每个空映射都相当于其他所有空映射,因此可以使用单个实例。这个堆栈溢出问题

我在线程“main”java.lang.UnsupportedOperationException中得到
异常
因为集合不可变不支持修改。那么这种数据结构有什么用呢

此类类和实用程序方法有什么用途

如果您正在返回一个
映射
结果,它通常是不可变的。。。例如,您可以创建一个不可变的映射来包装您自己的“真实”数据,而无需创建完整副本,或者信任调用方不会对其进行变异


此外,如果返回的是空的
映射
结果,则不必每次都创建一个新对象是很方便的-每个空映射都相当于其他所有空映射,因此可以使用单个实例。

这个堆栈溢出问题可能会有所帮助:使用不可变的空集()

这有助于实现空对象设计模式,即返回一个空映射,而不是Null

它(与emptyList和emptySet一起)用于返回一个空集合,而无需每次实例化一个新对象。

对于您的情况,我想对不可变的最好解释如下:

  • 该字段被声明为公共(以便于访问)。如果您没有将其定为最终版本,这意味着您可以随时访问,并获得如下代码:

    //somewhere in your program (or someone else's)
    Collections.EMPTY_MAP = new EmptyMap<"String","String">("unwantedKey","unwantedValue");
    
    //what do you actually want to do
    Map myMap = Collections.emptyMap();
    //you would expect an empty map, but you will get something else
    
    //程序中的某个地方(或其他人的)
    Collections.EMPTY_MAP=新的空映射(“unwantedKey”、“unwantedValue”);
    //你到底想做什么
    Map myMap=Collections.emptyMap();
    //你会期待一张空地图,但你会得到其他东西
    
    这将对您非常不利,因为您可能会看到您的程序行为将是错误的

  • 如果您阅读了第43项(返回空数组或集合,而不是null),建议您返回一个空集合,这样您就不必在开发时包含null数组操作代码。你也可以参考这个

    好的,那么这和不可变的空集合(或者您的例子中的映射)有什么关系呢? 假设您将在类中使用许多方法,并调用一个从集合中生成元素组的方法,然后返回组的集合,除非(此处插入随机条件)

    到目前为止还不错。假设您决定使用from(如果有,为什么没有?)。您可以在多个位置返回空地图,但在其中一些位置您希望修改它。您将引用EMPTY_映射修改为使用此引用的所有代码(这使我们回到了数字1。还记得在EMPTY_映射中所做的更改吗?)

  • 这就是内存减少之类的原因。如果它不是不可变的,并且每次需要空映射时都会创建新实例,那么这将导致(您可以说是严重的)内存(不是泄漏,而是)性能(我不太懂这个术语,但您知道)。也许你听说过,这是同样的事情

  • 好了。这是您需要不可变空映射的三个主要原因(我现在可以想到)

    为了解决你的问题,你不应该使用空地图,你应该自己创建一个。这并不难,你可以摆脱这些讨厌的(可怕的)不变的东西


    祝你好运

    我不确定..但我猜这对空对象模式之类的东西很有帮助。您可以返回空映射,而不是从方法返回空引用。可能的重复应该是注释而不是答案。
    public static final Map EMPTY_MAP = new EmptyMap<>();
    
    /**
     * @serial include
     */
    private static class EmptyMap<K,V>
        extends AbstractMap<K,V>
        implements Serializable
    {
        private static final long serialVersionUID = 6428348081105594320L;
    
        public int size()                          {return 0;}
        public boolean isEmpty()                   {return true;}
        public boolean containsKey(Object key)     {return false;}
        public boolean containsValue(Object value) {return false;}
        public V get(Object key)                   {return null;}
        public Set<K> keySet()                     {return emptySet();}
        public Collection<V> values()              {return emptySet();}
        public Set<Map.Entry<K,V>> entrySet()      {return emptySet();}
    
        public boolean equals(Object o) {
            return (o instanceof Map) && ((Map<?,?>)o).isEmpty();
        }
    
        public int hashCode()                      {return 0;}
    
        // Preserves singleton property
        private Object readResolve() {
            return EMPTY_MAP;
        }
    }
    
    Map myMap = Collections.emptyMap();
    myMap.put("Name","John");
    
    //somewhere in your program (or someone else's)
    Collections.EMPTY_MAP = new EmptyMap<"String","String">("unwantedKey","unwantedValue");
    
    //what do you actually want to do
    Map myMap = Collections.emptyMap();
    //you would expect an empty map, but you will get something else