What is the purpose of placing a HashSet inside of a HashMap? - java

For example:
private HashMap<Integer, HashSet> variableName;
I understand that HashMap implements Map and doesn't allow duplicate keys and HashSet implements Set and doesn't allow for duplicate values, but what is the purpose of placing a HashSet inside of a HashMap? Do they not achieve similar tasks by themselves (though in different ways and with different performance)? What functionality does doing this provide that a HashMap by itself couldn't?

You do this when you want to map a key to more than one thing. A Map can only map a key to a single thing, but that single thing can be a Set which holds multiple things.

Related

Hashmaps contain the same key

I have a
Stack<MyThread> rts;
each Thread contains a HashMap with a Custom Object Key.
HashMap<CustomObject> myMap = rts.pop().mapOfThread;
and I have the HashMap of these CustomObjectKeys
MyThread.CustomObjectMap
I need the fastest way to check if any of the HashMaps in the Threads in the Stack contains the same key as my CustomObject HashMap.
So, if I understand correctly, you have a number of disjoint HashMaps that may share keys, and you want to see if any keys are the same across any or all?
If so, I don't really see a solution other than iterating through the keySet() and checking each HashMap to see if the key is present, probably via containsKey().

Why key in HashMap can't be duplicated

I know how hash map works. We can't use duplicate keys in Hashmap. I want to know the logic behind this used by Sun people. How it has been coded that we can't store duplicate key in HashMap.
It's part of the contract of the Map interface:
An object that maps keys to values. A map cannot contain duplicate keys; each key can map to at most one value.
What should Map.get(key) return if a key has multiple values?
An HashMap is a data structure where is possible to save couples of key values. This data structure implements Map.
From javadoc:
A map cannot contain duplicate keys; each key can map to at most one value.
It is possible to retrieve directly a value using its key, so is not possible to have more values associated to the same key.
Instead is possible to have multiple keys pointing to the same value.
If you need a different data structure where multiple values are associated to the same key you can use libraries like Guava that has the concept of Multimap
Note: Using standard Map is possible to create a Map<MyKey, List> where you associate a list to a key. So you can also add multiple values to that key storing them in the associated list.

Sort a TreeMap by either Key Or Value

Situation:
I have a Map, a TreeMap to be more exact that looks like
TreeMap<String, Integer>
I have to be able to sort it on either the key OR the value in an ascending OR descending way. The result must be a Map like
Map<String, Integer>
Not an ArrayList or anything like that because the rest (read: allot) of my code won't work anymore. I've searched but couldn't find anything that suits my needs. Is this even possible? Double values may not be lost.
If you use two BiMaps which each back each other, then you effectively have one map.
Somthing like:
import com.google.common.collect.BiMap;
import com.google.common.collect.HashBiMap;
private BiMap<Integer, String> localid = HashBiMap.create();
private BiMap<String, Integer> inverse = localid.inverse();
you can treat each reference, localid & inverse, as their own map, but changes to one are reflected in the other. The only slight downside is that now both the keys and values must be unique, as the values of one are the keys of the other. For most cases this is not a problem.
For sorting it, you can at any time make a local copy which is a treeMap, and that imposes an ordering. E.g.
ImmutableMap.copyOf(Maps.newTreeMap(bimap))
Now if you are never making changes to your map, this will provide a sorted view, and you can do it by either.
EDIT: A TreebasedTable has two keys for each value, and you can sort either keyset with a comparator. I am not sure that this is exactly what you need, here as the keysets are independent, but you might be able to refactor your code slightly to make this a viable solution.
If the map is small and iterating over it is an infrequent operation, one solution would be to just use a HashMap (for lookup speed) and then sort the entries every time you iterate.
Another solution, if you do these iterations frequently compared to direct map lookups, and if the values (and not just the keys) are unique, would be to maintain two sorted maps, one <String, Integer> and one <Integer, String>.
Guava has the concept of BiMap. Is that what you're looking for?
A TreeMap's keys are sorted by it's comparable.
Try a SortedMap
A Map that further provides a total ordering on its keys. The map is ordered according to the natural ordering of its keys, or by a Comparator typically provided at sorted map creation time. This order is reflected when iterating over the sorted map's collection views (returned by the entrySet, keySet and values methods). Several additional operations are provided to take advantage of the ordering. (This interface is the map analogue of SortedSet.)

Does a HashMap use a HashSet to store its keys?

I'm wondering if a HashMap uses a HashSet to store its keys. I would guess it does, because a HashMap would correspond with a HashSet, while a TreeMap would correspond with a TreeSet.
I looked at the source code for the HashMap class, and the method returns an AbstractSet that's implemented by some kind of Iterator.
Additionally...when I write
HashMap map = new HashMap();
if(map.keySet() instanceof HashSet){
System.out.println("true");
}
The above if statement never runs. Now I'm unsure
Could someone explain how the HashMap stores its keys?
You're actually asking two different questions:
Does a HashMap use a HashSet to store its keys?
Does HashMap.keySet() return a HashSet?
The answer to both questions is no, and for the same reason, but there's no technical reason preventing either 1. or 2. from being true.
A HashSet is actually a wrapper around a HashMap; HashSet has the following member variable:
private transient HashMap<E,Object> map;
It populates a PRESENT sentinel value as the value of the map when an object is added to the set.
Now a HashMap stores it's data in an array of Entry objects holding the Key, Value pairs:
transient Entry<K,V>[] table;
And it's keySet() method returns an instance of the inner class KeySet:
public Set<K> keySet() {
Set<K> ks = keySet;
return (ks != null ? ks : (keySet = new KeySet()));
}
private final class KeySet extends AbstractSet<K> {
// minimal Set implementation to access the keys of the map
}
Since KeySet is a private inner class, as far as you should be concerned it is simply an arbitrary Set implementation.
Like I said, there's no reason this has to be the case. You could absolutely implement a Map class that used a HashSet internally, and then have your Map return a HashSet from .keySet(). However this would be inefficient and difficult to code; the existing implementation is both more robust and more efficient than naive Map/Set implementations.
Code snippets taken from Oracle JDK 1.7.0_17. You can view the source of your version of Java inside the src.zip file in your Java install directory.
I'm wondering if a HashMap uses a HashSet to store its keys.
That would not work too well, because a Set only keeps track of the keys. It has no way to store the associated value mapping.
The opposite (using a Map to store Set elements) is possible, though, and this approach is being used:
HashSet is implemented by using a HashMap (with a dummy value for all keys).
The set of keys returned by HashMap#keySet is implemented by a private inner class (HashMap.KeySet extends AbstractSet).
You can study the source for both class, for example on GrepCode: HashMap and HashSet.
Could someone explain how the HashMap stores its keys?
It uses an array of buckets. Each bucket has a linked list of entries. See also
How does Java HashMap store entries internally
Hashmap and how this works behind the scene
The set that is returned by the keySet is backed by the underlying map only.
As per javadoc
Returns a Set view of the keys contained in this map. The set is backed by the map, so changes to the map are reflected in the set, and vice-versa. If the map is modified while an iteration over the set is in progress (except through the iterator's own remove operation), the results of the iteration are undefined. The set supports element removal, which removes the corresponding mapping from the map, via the Iterator.remove, Set.remove, removeAll, retainAll, and clear operations. It does not support the add or addAll operations.
Blockquote
HashMap stores keys into buckets. Keys that have same hash code goes into the same bucket. When retrieving value for an key if more than one key is found in the bucket than equals method is used to find the right key and hence the right value.
Answer is: NO.
HashMap.keySet() is a VIEW of the keys contained in this map.
The data of the map is stored in Entry[] table of HashMap.

creating Trigrams using LinkedHashMap java

I am trying to create a trigram model using LinkedHashMap>
where Entry is the entry of last inputed bigram (whose structure is:
LinkedHashMap
Now the problem is, being a map it does not store multiple keys (overwrites the existing key-value pair with new key-value pair for existing key).
I am not sure whether a multimap will be useful for this or not? If so, how?
Every collections that implements Map interface keeps it's keys in Set implementation. Set can not keep multiple values.
Multimap is just a Map<Key, Collection<Value>>. It allows to keep multiple values under one key.
Read more about Maps.

Categories