我从HashMap获取HashSet,我不希望我对HashSet的修改反映在HashMap值上。
做这样的事情的最佳方式是什么:
HashSet<Object> hashset = new HashSet((Collection<Object>) hashmap.values());
//Something like ...
hashset.detach();
//Then i can modify the HashSet without modifying the HashMap values
修改: 我必须修改HashSet中的一个元素,但我不想在HashMap中修改这个相同的元素。
感谢!!!
答案 0 :(得分:6)
如果您根据代码段的第一行创建 new HashSet
,那么这已经是一个单独的集合。在集合中添加或删除项目不会更改hashMap
。当然,修改现有的项目 - 但这是另一回事,并且几乎总是非常糟糕(假设您的修改会影响对象相等)。
答案 1 :(得分:4)
当您从HashSet
这样创建hashMap.values()
时,它已经“分离”了,因为修改HashSet
不会影响它构建的地图。
但是,如果您在中修改对象(例如在其上调用setter),那么这些更改也将反映在HashMap
内(因为{{ 1}}和Set
将引用同一个对象。)
解决此问题的一种方法是使每个元素defensive copies(使用Map
或使用复制构造函数)。
另一种方法是使用immutable objects。
答案 2 :(得分:1)
你很近:
Set<Object> set = hashmap.values(); // is backed by the map
// create a new hashset seeded from the other set
Set<Object> hashset = new HashSet<Object>(set);
答案 3 :(得分:0)
如果您尝试复制值,并更改创建深层副本所需的值的状态,这取决于知道如何创建Map
中保存的对象的副本作为值。希望这个测试能说明我的意思。
@Test
public void testHashMap() throws Exception {
final Map<Integer, TestContainer<Double>> hashmap = new HashMap<Integer, TestContainer<Double>>();
final TestContainer<Double> t1 = new TestContainer<Double>(1d);
final TestContainer<Double> t2 = new TestContainer<Double>(2d);
hashmap.put(1, t1);
hashmap.put(2, t2);
// create a separate collection which can be modified
final Set<TestContainer<Double>> hashset = new HashSet<TestContainer<Double>>(hashmap.values());
assertEquals(2, hashmap.size());
assertEquals(2, hashset.size());
hashset.remove(t2);
assertEquals(2, hashmap.size());
assertEquals(1, hashset.size());
// prove that we cannot modify the contents of the collection
hashset.iterator().next().o += 1;
assertEquals(2d, t1.o, 0d);
}
private static final class TestContainer<T> {
private T o;
private TestContainer(final T o) {
this.o = o;
}
}
答案 4 :(得分:0)
试试这个:
public MyType cloneObject(MyType o) {
MyType clone = new MyType();
// TODO copy the attributes of 'o' to 'clone' return the clone
return clone;
}
public void populateHashSet(HashMap<Object,MyType> hashMap) {
HashSet<MyType> hashSet = new HashSet<MyType>();
for (MyType o : hashMap.values()) {
hashSet.add(cloneObject(o));
}
}
也就是说,除非对象的所有属性都是原始/不可变类型,否则我会非常小心地创建对象的副本。如果只是将属性对象引用复制到克隆中的对象引用,那么“克隆”仍然可以通过更改它引用的对象在原始对象中产生副作用。