我正在尝试使用set作为缓冲区来保存一些值,将它们存储在地图中,然后重置自己以准备下一个数据流。以下是一些相关代码:
Map<Set<String>, Integer> map = new LinkedHashMap<Set<String>, Integer>();
Set<String> set = new LinkedHashSet<String>();
set.add("A");
map.put(set, 1);
for (Set<String> entry : map.keySet()) {
for (String word : entry) {
System.out.println("BEFORE CLEAR - "+word);
}
}
set.clear();
for (Set<String> entry : map.keySet()) {
System.out.println("AFTER CLEAR - "+entry.size());
for (String word : entry) {
System.out.println("AFTER CLEAR - "+word);
}
}
我得到的输出是:
BEFORE CLEAR - A
AFTER CLEAR - 0
如果我将set.clear()
更改为set = null
,则输出为:
BEFORE CLEAR - A
AFTER CLEAR - 1
AFTER CLEAR - A
这意味着当我清除设置中的数据后将其放入地图时,地图不会收到新的副本 - 这就是为什么在清除集合时,地图中的副本也会被清除。 我对这种行为感到惊讶,因为作为Java开发人员,我们被迫使用不可变副本,这似乎在这里被违反了。我误解了什么吗?
我的问题是,这个问题有更好的解决方案吗?它适用于将set设置为null,我必须在while循环中每次使用新的LinkedHashSet()重新初始化。这对我来说很糟糕。
编辑:我没有设置设置为null的问题,我当然希望地图中的数据。我只是在创建set的新对象时遇到问题,而不是使用相同的对象。
答案 0 :(得分:2)
如果你制作set = null
,你将删除对一个集合的本地引用,但你的地图仍将保留对设置对象的引用。要从map中删除set,您需要map.remove(set)
Java在将其作为参数传递时不进行深度集复制,唯一复制的是对象的引用。如果您希望您的设置保存所有数据,那么只是不清除它 - 当您需要另一个空数据时创建新设置。当你写一些像
Set<String> set = new LinkedHashSet<String>();
第一部分Set<String> set
是一个引用(类似于C中的指针)到那段内存,第二部分new LinkedHashSet<String>();
实际上是分配这些内存。如果你清除那块内存中的东西(set.clear())你会删除写在那里的东西。如果您需要新的内存来编写新数据而不删除旧数据,则需要再次调用new LinkedHashSet<String>();
。
答案 1 :(得分:0)
首先,你是正确,而且有时麻烦,但Java中的Collections
确实可变强>
其次,我认为您确实需要复制Set
的内容,将该内容放入Map
,而不是将引用添加到Set
map.put(set, 1);
1}},如果你想稍后清除它。因此,我建议你简单地替换:
map.put(new HashSet<>(set), 1);
由:
Set
在我看来,这很有道理,因为:
Set