Java storage and lookup of HashMap in HashSet - java

I have a set with multi-dimensional hashmaps, like so:
Set<HashMap<String, HashMap<String, String>>> myHashSet = new HashSet<HashMap<String, HashMap<String, String>>>();
I am having trouble removing a HashMap entry. I know the key for the top level hashmap, but do not know any data in the underlying hashmap. I am trying to remove a hashmap entry in the set in these ways:
I.
Set<HashMap<String, HashMap<String, String>>> myHashSet = new HashSet<HashMap<String, HashMap<String, String>>>();
... Add some hashmaps to the set, then ...
String myKey = "target_key";
setInQuestion.remove(myKey);
II.
Set<HashMap<String, HashMap<String, String>>> myHashSet = new HashSet<HashMap<String, HashMap<String, String>>>();
... Add some hashmaps to the set, then ...
String myKey = "key_one"; //Assume a hashmap has been added with this top level key
HashMap<String, HashMap<String, String>> removeMap = new HashMap<String, HashMap<String, String>>();
HashMap<String, String> dummyMap = new HashMap<String, String>();
removeMap.put(myKey, dummyMap);
setInQuestion.remove(removeMap);
Neither of these methods work. How would I go about removing an entry in the set if I only know the top level hashmap's key?

Collection.remove() requires object equality. the various jdk Map implementations implement equality to mean all keys/values must match. Since none of the objects you are passing to the remove() call would be "equal" to any of the Maps in the Set, nothing is being removed.
the only way to do what you want is to iterate through the Set yourself to find the matching Map (or, make the Set into a Map keyed on that special key).

Thanks jtahlborn for the guidance. Wanted to post the solution I've found as a result of your answer:
String myKey = "Key_In_Question";
Iterator mySetIterator = myHashSet.iterator();
while(mySetIterator.hasNext()) {
HashMap<String, HashMap<String, String>> entry = (HashMap<String, HashMap<String, String>>) mySetIterator.next();
if(entry.containsKey(myKey)) {
myHashSet.remove(entry);
}
}

Sorry I couldn't post this as a comment. I wanted to point out that #jtahlborn's point about Map equality is a well-defined part of the contract... see Map.equals.
... two maps m1 and m2 represent the same mappings if m1.entrySet().equals(m2.entrySet()). This ensures that the equals method works properly across different implementations of the Map interface.
Map.Entry.equals is worded similarly.
... two entries e1 and e2 represent the same mapping if
(e1.getKey()==null ?
e2.getKey()==null : e1.getKey().equals(e2.getKey())) &&
(e1.getValue()==null ?
e2.getValue()==null : e1.getValue().equals(e2.getValue()))
This ensures that the equals method works properly across different implementations of the Map.Entry interface.

Related

How to retrieve common key value pairs from two hashmaps

I have two hashmaps:
Map<String, String> mapA = new HashMap<String, String>();
Map<String, String> mapB = new HashMap<String, String>();
TreeSet<String> uniquekeys = new TreeSet<String>();
mapA.put("1","value1");
mapA.put("2","value2");
mapA.put("3","value3");
mapA.put("4","value4");
mapA.put("5","value5");
mapA.put("6","value6");
mapA.put("7","value7");
mapA.put("8","value8");
mapA.put("9","value9");
mapB.put("1","value1");
mapB.put("2","value2");
mapB.put("3","value3");
mapB.put("4","value4");
mapB.put("5","value5");
To get the common key value pairs from the two hashmaps, I have written the below logic:
uniquekeys.addAll(mapA.keySet());
uniquekeys.addAll(mapB.keySet());
and then use the keys from the treeset: uniquekeys to retrieve unique key value pairs from mapA & mapB.
But this is not giving me the details of all the keys from mapA. I understand this way is flawed but I couldn't come up with a proper logic.
Could anyone let me know how can I retrieve key value pairs that are common in mapA and mapB into a new HashMap ?
Try below logic :
Map<String, String> common = new HashMap<String, String>();
for(String key : mapA.keySet()) {
if(mapB.get(key) !=null ) {
if(mapA.get(key).equals(mapB.get(key))) {
common.put(key, mapA.get(key));
}
}
}
You can do it with Java 8 Streams in the following way:
Map<String, String> commonMap = mapA.entrySet().stream()
.filter(x -> mapB.containsKey(x.getKey()))
.collect(Collectors.toMap(x -> x.getKey(), x -> x.getValue()));
Instead of adding all keys to a TreeSet, you can fill the TreeSet with common values:
uniquekeys.addAll(mapA.keySet());
uniquekeys.retainAll(mapB.keySet());
This way, the keys contained in A but not B will be removed. Know you've got your TreeSet, you can do what you want.
However, you can also create your HashMap without TreeSet, as #Ramesh and #NiVeR suggest
Use Guava Util Sets
Set<String> intersectionSet = Sets.intersection(firstSet, secondSet);

How can I combine two HashMap objects containing the different types?

I have two HashMap objects defined as:
Map<String, String> requestParams = new HashMap<>();
Map<String, Boolean> requestParamForOauth = new HashMap<>();
How can I merge these two maps?
Assuming that both maps contain the same set of keys, and that you want to "combine" the values, the thing you would be looking for is a Pair class, see here for example.
You simply iterate one of the maps; and retrieve values from both maps; and create a Pair; and push that in your result map.
The only downside is that there is no "official" Pair class that you could use (see here for more thoughts around that).
Alternatively, if there is a "deeper" meaning of those "combined" values (beyond a simple "tuple/pair" semantics), you could instead create your own class that wraps around those two values.
Your keys are of the same type (String), but the values are not even related by an interface or super class, you will need to define a Map<String, Object> and make use of the Map#putAll method
Map<String, String> requestParams = new HashMap<>();
Map<String, Boolean> requestParamForOauth = new HashMap<>();
Map<String, Object> requestParamForOauth2 = new HashMap<>();
requestParamForOauth2.putAll(requestParams);
requestParamForOauth2.putAll(requestParamForOauth);
If you want to use one list to store all the data You can
use one HashMap<String,Object>
What do you want to do when the same key appears in both Map? If you want to keep both the String and Boolean, then you'll need a map that looks like this: Map<String, Pair(String, Boolean)>. If you just want to keep one value, then Map<String, Object> is what you want.

Add HashMap to another HashMap

When i try to add hashMap to another HashMap i lose old varaible. How can i fix this problem? My code is something like that.
HashMap<String, String> tmp = new HashMap<String, String>();
HashMap<String, String> map = new HashMap<String, String>();
tmp = ((HashMap<String, String>)intent.getSerializableExtra("map"));
map.putAll(tmp);
when i use this code map elements always equals tmp elements. It is not stored old elements.
Thanks for help.
HashMap<String, String> map = new HashMap<String, String>(); creates a new, empty, HashMap instance. Therefore after a call to map.putAll(tmp), your map would only contain the entries of tmp.
If map has previous entries, you shouldn't assign a new instance to this variable.
That said, even if map had previous entries, putting the entries of tmp in it would overwrite the values of all the keys that exist in both map and tmp.
Once you have updated map to not be re-initialized every time, you can avoid overwriting any existing key-value pairs in map by looping as follows:
for (String key : tmp.keySet()) {
if (!map.containsKey(key)) {
map.put(key, tmp.get(key);
}
}
I'm not sure from your question if this is exactly what you are asking, but it may be useful. Eran's suggestion (using HashMap<String, List<String>>) is also a good one if you want to store multiple Strings per key.

HashMap from List of Files

I'd like to explore the option of using a HashMap to keep track of changes between files. I'm using a few config/text files to give a set of documents of status:
The config file looks like:
STATUS1 = "Doc1.pdf, Doc2.xls, Doc5.doc"
STATUS2 = "Doc8.pdf, Doc6.doc"
STATUS3 = "Doc10.pdf"
...
Instead of having to create a separate HashMap for each instance like so:
Map<String, String> map1 = new HashMap<String, String>();
Map<String, String> map2 = new HashMap<String, String>();
Map<String, String> map3 = new HashMap<String, String>();
map1.put("STATUS1", "Doc1.pdf");
map2.put("STATUS1", "Doc2.xls");
map3.put("STATUS1", "Doc5.doc");
I'd like to have only a single Map with the key of the status and the values mapped to that key.
I don't need help in parsing the file, I just need assistance in implementing the HashMap or Map so I can add this functionality. If there are other datatypes or methods of organizing this data, I'd like to hear your opinions on that.
Any help would be much appreciated.
You can use a MultiMap, which stores multiple values for the same key.
Multimap
Multimap<String, String> myMultimap = ArrayListMultimap.create();
// Adding some key/value
myMultimap.put("STATUS1", "somePDF");
myMultimap.put("STATUS1", "someDOC");
myMultimap.put("STATUS1", "someXCL");
myMultimap.put("STATUS2","someFormat");
// Getting the size
int size = myMultimap.size();
System.out.println(size); // 4
// Getting values
Collection<string> stats1 = myMultimap.get("STATUS1");
System.out.println(stats1); // [somePDF, someDOC, someXCL]
2 . HashMap
With HashMap you can have something like,
List<String> listOfDocs = new ArrayList<String>();
listOfDocs.add("somePDF");
listOfDocs.add("someDOC");
listOfDocs.add("someFormat");
HashMap<String, ArrayList<String>> map = new HashMap<String, ArrayList<String>>();
// key would be your STATUS
// Values would be ListOfDocs you need.
map.put("STATUS1", listOfDocs);
map.put("STATUS2", listOfDocs2);
map.put("STATUS3", listOfDocs3);
Hope this helps.
Let me know if you have questions.

How to remove elements of one map from another map?

HashMap<String, String> foo = new HashMap<String, String>();
HashMap<String, String> baar = new HashMap<String, String>();
How to remove items found in baar from foo?
You can try:
foo.keySet().removeAll(baar.keySet())
Changes to a Map's keySet() are reflected in the map itself.
If you want to remove exact mappings (not just based on keys), you can use the same approach with the entrySet() instead:
foo.entrySet().removeAll(baar.entrySet());

Categories