Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/variables/2.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 静态初始化的unmodifiableCollection.get是否保证不可变?_Java_Collections_Immutability - Fatal编程技术网

Java 静态初始化的unmodifiableCollection.get是否保证不可变?

Java 静态初始化的unmodifiableCollection.get是否保证不可变?,java,collections,immutability,Java,Collections,Immutability,静态初始化的unmodifiableCollection.get是否保证不可变 用于: 静态最终映射FOO= Collections.unmodifiableMap(新的HashMap()) 多线程可以使用方法get而不遇到问题吗 即使无法添加/删除FOO中的项,是什么阻止get方法为缓存目的操纵FOO的内部状态等。如果以任何方式修改了内部状态,那么FOO就不能同时使用。如果是这种情况,java中真正的不可变集合在哪里?我建议任何线程操作都使用ConcurrentHashMap或HashTabl

静态初始化的unmodifiableCollection.get是否保证不可变

用于:

静态最终映射FOO= Collections.unmodifiableMap(新的HashMap())

多线程可以使用方法get而不遇到问题吗


即使无法添加/删除FOO中的项,是什么阻止get方法为缓存目的操纵FOO的内部状态等。如果以任何方式修改了内部状态,那么FOO就不能同时使用。如果是这种情况,java中真正的不可变集合在哪里?

我建议任何线程操作都使用ConcurrentHashMap或HashTable,两者都是线程安全的

Java SDK中没有真正的不可变映射。Chris建议的所有地图都是线程安全的。不可修改的映射也不是不可变的,因为如果基础映射发生更改,也会出现
ConcurrentModificationException


如果您想要真正的不可变映射,请使用Google Collections/Guava提供的不可变映射。

只要对象遵守其契约(即不能修改的映射),则返回映射上的getter是否碰巧与某些内部状态混在一起并不重要。所以你的问题是“找错人了”

如果您对它所包装的地图没有所有权和控制权,您应该谨慎使用不可修改的地图。比如说

Map<String,String> wrapped = new HashMap<String,String>();
wrapped.add("pig","oink");
Map<String,String> wrapper = Collections.unmodifiableMap(wrapped);
System.out.println(wrapper.size());
wrapper.put("cow", "moo"); // throws exception
wrapped.put("cow", "moo");
System.out.println(wrapper.size()); // d'oh!
Map wrapped=newhashmap();
包装。添加(“猪”、“猪”);
映射包装器=集合。不可修改映射(已包装);
System.out.println(wrapper.size());
包装纸。放(“牛”,“哞”);//抛出异常
包好。放(“牛”,“哞”);
System.out.println(wrapper.size());//哦!

实际上是个好问题。想想看
WeakHashMap
——它可以在不调用突变操作的情况下改变<访问顺序模式下的code>LinkedHashMap基本相同

HashMap
的API文档状态:

请注意,此实现不是 已同步。如果有多个线程 同时访问哈希映射,并在 至少有一个线程修改 在结构上,它必须是 外部同步。(A)结构 修改是指任何需要修改的操作 添加或删除一个或多个映射; 仅仅改变相关的价值 使用已创建实例的密钥 contains不是一个结构 修改。)


想必这应该是当且仅当。这意味着如果
HashMap
是“有效不可变的”,则不需要同步
get

给定具体示例:

static final Map FOO = Collections.unmodifiableMap(new HashMap());
那么FOO将是不可变的。它也永远不会有任何元素。考虑到以下更一般的情况:

static final Map BAR = Collections.unmodifiableMap(getMap());
那么这是否是不可变的完全取决于其他人是否可以访问底层映射,以及它是什么类型的映射。例如,如果它是LinkedHashMap,则可以通过访问顺序修改基础链接列表,并可以通过调用get()进行更改。最安全的方法(使用非并发类)是:

static final Map BAR = Collections.unmodifiableMap(new HashMap(getMap()));
这意味着,只要不对映射进行结构更改,那么并发使用它是安全的,因此这对于您可以使用的任何访问器都应该是安全的,即获取各种集合并对其进行迭代,然后get()应该是安全的

如果可以使用并发类,则还可以执行以下操作:

static final Map BAR = Collections.unmodifiableMap(new ConcurrentHashMap(getMap());

由于ConcurrentHashMap是显式多线程访问安全的,因此从多线程使用它将显式安全。内部状态可能是可变的,但外部可见状态将不存在,并且由于类被保证是线程安全的,所以我们可以安全地认为它是外部不变的。

< P>在听起来像我在广告狂欢中的风险时,使用它并完成它。

实际上是个好问题。想想看,
WeakHashMap
——它可以在不改变的情况下改变<访问顺序模式下的code>LinkedHashMap是相同的。(您可能希望将问题标题复制到问题横幅中。)作者提出了一个好问题。假设我编写了自己的map实现。假设每次查找时,它都会重新组织其内部结构,以便下次更快地找到查找最多的项。用户用一个不可修改的集合包装所述地图,并假设它是线程安全的。然后两个线程同时访问不同的值,内部优化器就会破坏映射的内部状态。z5h:如果你小心,你可以吃蛋糕。我曾经写过一个专家图(用于
ThreadLocal
实现),它不是每个bucket都有一个单独链接的列表,而是一个单独链接的循环。如果错过了在循环链接中命中条目的快速路径,它会将命中条目的引用写回数组。这是线程安全的。是的,对不可变数据使用并发操作可能是个坏主意。如果我,比如说,想在
条上迭代
?@Tom:正如你在回答中提到的,我现在在我的回答中提到;-),在映射上迭代应该和使用get一样安全。但是您正在谈论未指定实现的
ConcurrentHashMap
map
s。根据定义,从多个线程使用ConcurrentHashMap是安全的。而且,我不是在说使用未指定的映射,这就是为什么我创建一个新的HashMap来传递到unmodifiableMap(),显式地让我们知道它是一个HashMap,而不是其他东西。先生/女士Downvoter:我的答案有什么问题吗,或者仅仅是报复?为什么你会无缘无故地引入这样的依赖关系?为什么在其他人已经有了依赖关系的情况下跳过障碍来确保不可变性?汤姆,有些人只是对
public static final Map=ImmutableMap.of(foo1,bar1,foo2,bar2)有一种风格偏好
over
publicstaticfinalmap=initMap();私有静态映射initMap(){Map Map=new HashMap()