Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to make a set backed by a map?

There is a method in the Collections class.

Set<E> Collections.newSetFromMap(<backing map>)

What does it mean by the backing map and the set backed by a map?

like image 361
Heggi Avatar asked Nov 23 '12 07:11

Heggi


People also ask

Can a Set be used as a Map key?

You should strive to use immutable types as keys for Map s. Collections and sets are generally very easily mutable so usually are a bad idea to use this way. If you want to use many key values as a Map key you should use a class implementation designed for that purpose, like Apache Commons Collections MultiKey .

Can we convert Map to Set Java?

To convert, Java Map to Set , we can use the conventional constructor with HashSet , however, there are few things to consider before we proceed with the conversion.

How do you store a value on a Map?

a) The values can be stored in a map by forming a key-value pair. The value can be retrieved using the key by passing it to the correct method. b) If no element exists in the Map, it will throw a 'NoSuchElementException'. c) HashMap stores only object references.


1 Answers

Perhaps it would be illuminating to look at the implementation:

private static class SetFromMap<E> extends AbstractSet<E>
    implements Set<E>, Serializable
{
    private final Map<E, Boolean> m;  // The backing map
    private transient Set<E> s;       // Its keySet

    SetFromMap(Map<E, Boolean> map) {
        if (!map.isEmpty())
            throw new IllegalArgumentException("Map is non-empty");
        m = map;
        s = map.keySet();
    }

    public void clear()               {        m.clear(); }
    public int size()                 { return m.size(); }
    public boolean isEmpty()          { return m.isEmpty(); }
    public boolean contains(Object o) { return m.containsKey(o); }
    public boolean remove(Object o)   { return m.remove(o) != null; }
    public boolean add(E e) { return m.put(e, Boolean.TRUE) == null; }
    public Iterator<E> iterator()     { return s.iterator(); }
    public Object[] toArray()         { return s.toArray(); }
    public <T> T[] toArray(T[] a)     { return s.toArray(a); }
    public String toString()          { return s.toString(); }
    public int hashCode()             { return s.hashCode(); }
    public boolean equals(Object o)   { return o == this || s.equals(o); }
    public boolean containsAll(Collection<?> c) {return s.containsAll(c);}
    public boolean removeAll(Collection<?> c)   {return s.removeAll(c);}
    public boolean retainAll(Collection<?> c)   {return s.retainAll(c);}
    // addAll is the only inherited implementation

    private static final long serialVersionUID = 2454657854757543876L;

    private void readObject(java.io.ObjectInputStream stream)
        throws IOException, ClassNotFoundException
    {
        stream.defaultReadObject();
        s = m.keySet();
    }
}

Edit - added explanation:

The map that you provide is used as the m field in this object.

When you add an element e to the set, it adds an entry e -> true to the map.

public boolean add(E e) { return m.put(e, Boolean.TRUE) == null; }

So this class turns your Map into an object that behaves like a Set by simply ignoring the values that things are mapped to, and just using the keys.

like image 152
Chris Martin Avatar answered Sep 20 '22 06:09

Chris Martin