繁体   English   中英

用Java将集合与地图分离的最佳方法是什么?

[英]What's the best way to detach a Collection from a Map in Java?

我从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中的相同的元素。

谢谢!!!

如果您要按照代码段的第一行创建一个新的 HashSet ,则这已经是一个单独的集合。 从集合中添加或删除项目不会更改您的hashMap 当然,修改现有项将是-但这是另一回事,并且几乎总是一件很糟糕的事情(假设您所做的修改会影响对象的相等性)。

当您像这样从hashMap.values()创建HashSet ,就意味着修改HashSet不会影响从其构造的地图,因此它已经“分离”了。

但是,如果您在集合修改对象(例如,在其上调用一个setter),则这些更改也将反映在HashMap内部(因为SetMap将引用同一对象)。

解决此问题的一种方法是制作每个元素的防御性副本 (使用clone()或使用副本构造函数)。

另一种方法是使用不可变对象

您接近:

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);

如果要复制值并更改值的状态,则需要创建深层副本,这取决于知道如何将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;
    }
}

尝试这个:

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));
    }
}

也就是说,除非对象的所有属性都是原始/不变类型,否则我将非常小心地复制对象。 如果仅将属性对象引用复制到克隆中的对象引用,则“克隆”仍可以通过更改其引用的对象在原始对象中产生副作用。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM