haxtar
haxtar

Reputation: 2070

Java: updating hashsets of hashsets

In the example below, the BigSet HashSet is made up of SmallSet HashSets. I'd like to clear SmallSet without clearing BigSet.

Instead, when I perform the clear() command on SmallSet, BigSet is also cleared. Why does this happen? And how can I only clear SmallSet, while leaving BigSet intact?

I've included print statements to illustrate what is going on.

import java.util.HashSet;
import java.util.Set;
import java.util.Arrays;

public class G{
    public static final HashSet<HashSet> BigSet = new HashSet <HashSet>();
    public static final HashSet<Set> SmallSet = new HashSet<Set>();

    public static Set<Integer> method() {
        Set<Integer> n = new HashSet<Integer>(Arrays.asList(10, 20, 30));
        SmallSet.add(n);
        BigSet.add(SmallSet);
        System.out.println(SmallSet);
        System.out.println(BigSet);
        SmallSet.clear();
        System.out.println(SmallSet);
        System.out.println(BigSet);
        return n;
    }

    public static void main(String[] args) {
        method();
    }
}

Output:

[[20, 10, 30]]
[[[20, 10, 30]]]
[]
[[]]

Upvotes: 0

Views: 368

Answers (2)

sprinter
sprinter

Reputation: 27956

You are not correct that you are clearing bigSet when you clear smallSet. smallSet is still inside bigSet, it's just that's it's now empty (because you cleared it). So when you see [[]] from the print statement it is telling you that bigSet now contains a single, empty set (specifically the now empty smallSet).

I suspect your misunderstanding is that you are imagining that bigSet is taking a copy of smallSet when you add it. It isn't. It's adding a reference to the same object referred to by the variable smallSet. When you call smallSet.clear you are clearing the set object referenced both by the variable and by bigSet.

If you actually wanted a copy of smallSet inside bigSet the simplest thing to do would be to create a new set instead of clearing smallSet:

bigSet.add(smallSet);
smallSet = new HashSet<>();

Upvotes: 1

corsiKa
corsiKa

Reputation: 82559

When you add SmallSet to BigSet you add the set itself, not the set inside it. So you could either

BigSet.add(new HashSet(SmallSet));

or

BigSet.addAll(SmallSet);

I personally recommend the later.

Note however, that because you're adding the Set to small set, if you did the following:

    Set<Integer> n = new HashSet<Integer>(Arrays.asList(10, 20, 30));
    SmallSet.add(n);
    BigSet.addAll(SmallSet);
    n.remove(20);
    System.out.println(BigSet);

You would get [10, 30] because it's the SET and not the SET'S ELEMENTS that were added to BigSet.

Also, when I was working on things like this in school, I was strongly encouraged to "draw boxes" - physical boxes on a chalkboard or whiteboard or paper. In this case you might even want to use note cards and putting them on top of each other to show what is in where. It really helps wrap your brain around it.

Upvotes: 1

Related Questions