Java 为什么我们有不变的空映射?
我在线程“main”java.lang.UnsupportedOperationException中得到Java 为什么我们有不变的空映射?,java,collections,map,immutability,Java,Collections,Map,Immutability,我在线程“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