views:

422

answers:

5

Hi,

I have a pretty big (100'000s of entries) HashMap. Now, I need a HashSet containing all the keys from this HashMap. Unfortunately, HashMap only has a keySet() method which returns a Set but not a HashSet.

What would be an efficient way to generate such a HashSet using Java?

+4  A: 
HashSet myHashSet = new HashSet(myHashMap.keySet());

Haven't tried it.

Sinuhe
+3  A: 

Can you not create the HashSet from an existing Set ? But (more importantly) why are you worried about the implementation returned to you from the keySet() method ?

Brian Agnew
+2  A: 

Set set=new HashSet(map.keySet());

Telcontar
+10  A: 

Why do you specifically need a HashSet?

Any Set have the same interface, so typically can be used interchangeably, as good-practices requires that you use the Set interface for all of them.


If you really need so, you could create one from the other. For generic code, it could be:

    Map<B, V> map = ...;
    HashSet<B> set = new HashSet<B>(map.keySet());
KLE
If you're going to do it this way, why not just use `Set<B> set = map.keySet();` ? If an actual HashSet is needed, `set` should be a HashSet, not a Set. If `set` can be a `Set`, then there's no need to call the HashSet constructor
Kip
Thanks, next time I better RTFM ;)
Haes
@Kip Thanks for your useful comment. I slightly clarified my code sample to take it into account.
KLE
Kip: you're right. Actually, I used the following code: HashSet<B> set = new HashSet<B>(map.keySet());
Haes
+6  A: 

Assuming that the word 'efficient' is the key part of your question, and depending what you want to do with the set, it might be an idea to create your own subclass of HashSet which ignores the HashSet implementation and presents a view onto the existing map, instead.

As a partially implemented example, it might look something like:

public class MapBackedHashSet extends HashSet
{
    private HashMap theMap;

    public MapBackedHashSet(HashMap theMap)
    {
        this.theMap = theMap;
    }

    @Override
    public boolean contains(Object o) 
    {
        return theMap.containsKey(o);
    }

    /* etc... */
}

If you don't know how the class will be used, you'll need to take care to override all the relevant methods.

izb
It should be a SetBackedHashSet to work for him, using a Set as the backing data. The original object he's getting from `keySet()` is a Set, not a HashMap.
Kip
The point is that you don't need to extract the set in this way. This is to avoid creating a new hash from a potentially large number of objects.
izb