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().
Related
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.
I am mapping a time table in the format of: Map<Route, List<Service>> read(String fileName)
Can I have multiple Lists on the same key? For example:
timeTable.put(route66,["32","55","33","12","15"]);
timeTable.put(route66,["66","5","33","43","77"]);
timeTable.put(route66,["12","56","33","67","35"]);
No, the contract for Map clearly states:
A map cannot contain duplicate keys; each key can map to at most one value.
In addition, your code isn't close to valid Java, as arrays aren't Lists, and those are strings, not whatever Service might be.
You might, however, be interested in Guava's Multimap, which is essentially a map from keys to a collection of values.
No you can't, Map keys are unique. In your case, the last value will override the others.
What you may want to do is have a map like Map<Route, List<String[]>>. It means that any entry you have will contain a list of String arrays
No you cannot. But you may keep for the same key a List of your lists:
Map<Route, List<List<Service>>>
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.)
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.
I am having two Hashtables with <int,string> pair. Now they both have duplicate values in each of them, and I want to merge both the hashtables to give me distinct values. How can I do that!?
thanks
Edit #1 I am reading file contents from a directory. and storing those contents as tokens in two different hashtables. Now I need to merge them into a single hashtable which would give me distinct values of both the tables.
You can use the putAll method of Hashtable to merge two hashtables. The hashtable passed as an argument will overwrite duplicates in the original hashtable.
I didn't get how two hashtables can be merged and still have distinct values. If you want to remove duplicate items from one hashtable (and leave them in the second hashtable) just do as suggested in another answer, but without adding non-duplicate items to map2. After that you will have the first table unmodified and the second with entries which aren't in map1.
Another solution is to merge two hashtables using putAll and clear the second hashtable :)
I guess you mean duplicate keys, not duplicate values. Also, since Hashtable is a map implementation, I'll provide a generic map solution.
// assuming the maps are of type String / String
for(Map.Entry<String, String> entry : map1.entrySet()){
if(map2.containsKey(entry.getKey()){
map2.remove(entry.getKey());
}else{
map2.put(entry.getKey(), entry.getValue());
}
}
Now map2 is the merged version with all duplicates removed
But if you want a Map without duplicate values, that's pretty cumbersome to achieve. Maybe you should check out the BidiMap interface in apache commons / collections. It provides maps were both keys and values are unique.
Actually, here's a simple way to remove duplicate values:
Collection<String> values1 = map1.values();
Collection<String> values2 = map2.values();
Collection<String> values1Copy = new ArrayList<String>(values1);
Collection<String> values2Copy = new ArrayList<String>(values2);
while(values1.removeAll(values2Copy)){}
while(values2.removeAll(values1Copy)){}
Now all duplicate values are removed from both maps. (This is assuming you want to delete the dupes entirely. If you want to keep one copy, use the values1 and values2 collections in the while loops and don't take copies.)
The original question-asker asserted in the comments that he means value, not key. This makes the question incomplete. In order to have duplicate values in two different tables, the key generation algorithm must be different. If that's the case, the bit of information that is missing from the question is which key does he want to retain? The one from the first hashtable or the one from the second?
The solution presented above by S.P.Floyd-seanizer is correct but needs a tiny bit of logic added if he really, really mean values. this additional logic would tell the code which key to put the thing under in the merged version.
if the question-asker is having 'value' and 'key' confusion then his solution is spot on.