在 Java 中从 Map 分离 Collection 的最佳方法是什么?

发布于 2024-09-19 04:22:22 字数 399 浏览 2 评论 0原文

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

谢谢!!!

I obtain a HashSet from a HashMap and I don't want that my modifications on the HashSet reflect on the HashMap values.

What's the best way of doing something like this :

HashSet<Object> hashset = new HashSet((Collection<Object>) hashmap.values());
//Something like ...
hashset.detach();
//Then i can modify the HashSet without modifying the HashMap values

Edit :
I have to modify an element in the HashSet but I don't want to modify this same element in the HashMap.

Thanks!!!

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

一百个冬季 2024-09-26 04:22:56

试试这个:

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

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

Try this:

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

That said, I would be very careful about making copies of objects unless all the attributes of the object are primitive/immutable types. If you just copy an attribute object reference to an object reference in the clone then your 'clone' can still produce side-effects in the original object by changing the objects it references.

甜警司 2024-09-26 04:22:52

如果您尝试复制值并更改值的状态,则需要创建深层复制,这依赖于了解如何创建 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;
    }
}

If you are trying to copy the values, and change the state of the values you need to create a deep copy, which relies on knowing how to create copies of the objects held in the Map as values. Hopefuly this test illustrates what I mean.

@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;
    }
}
莫相离 2024-09-26 04:22:47

你很接近:

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

You are close:

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);
心舞飞扬 2024-09-26 04:22:42

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

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

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

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

When you create the HashSet from hashMap.values() like this, then it's already "detached" in the sense that modifying the HashSet will not influence the map it was constructed from.

However, if you modify an object inside the set (for example calling a setter on it), then those changes will be reflected inside the HashMap as well (since the Set and the Map will refer to the same object).

One way around this is to make defensive copies of each element (using clone() or by using a copy constructor).

Another way is to use immutable objects.

扬花落满肩 2024-09-26 04:22:38

如果您根据代码片段的第一行创建一个 HashSet,那么它已经是一个单独的集合。从集合中添加或删除项目不会更改您的 hashMap。当然,修改现有项目会 - 但那是另一回事,并且几乎总是一件非常糟糕的事情(假设您的修改影响对象平等)。

If you're creating a new HashSet as per the first line of your code snippet, that's already a separate collection. Adding or removing items from the set won't change your hashMap. Modifying the existing items will, of course - but that's a different matter, and will almost always be a Very Bad Thing (assuming your modifications affect object equality).

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文