Merging Map of LinkedHashMap - java

I have two Map of LinkedHashMap in this format==> Map<String,LinkedHashMap<String,String>> both m1 & m2 have same key values, How we combine this m1 & m2 and make m3 with all elements.
Note :Can you some one give psuedocode I will implement it.Thanks.
Input is like below format:
m1={1={rollno=1,name=chris,height=7ft},2={rollno=2,name=stephen,height=6ft}}
m2={1={rollno=1,name=chris,weight=65},2={rollno=2,name=stephen,weight=73}}
Output :
m3={1={rollno=1,name=chris,height=7ft,weight=65},2={rollno=2,name=stephen,height=6ft,weight=73}}
What I tried :
private static Map<String, LinkedHashMap<String, String>> mergeMap(Map<String,LinkedHashMap<String, String>> m1, Map<String, LinkedHashMap<String, String>> m2) {
Map<String,LinkedHashMap<String, String>> newMap = new LinkedHashMap<String, LinkedHashMap<String, String>>(m1);
for (Map.Entry<String, LinkedHashMap<String, String>> entry : m2.entrySet()) {
LinkedHashMap<String, String> t1=newMap.get(entry.getKey());
newMap.putAll(m2);
}
System.out.println("ouput :"+newMap);
return newMap;
}

You can follow the steps below to merge the maps:
First create a newMap, passing first map - map1 as parameter. You have to use the overloaded constructor - LinkedHashMap(Map) for that. Now you have a map with all the elements of map1. Half of your job is done.
Map<String, Map<String, String>> newMap = new LinkedHashMap<>(map1);
Then you need to move elements from 2nd map to the newMap. For that, you would need to iterate over map2. You can use Map#entrySet() method to iterate over each entry in map2. You would then use Map.Entry#getKey() and Map.Entry#getValue() methods to get the key and value respectively for each entry.
For each key in map2, get the current value from newMap, and merge the value of map2, with the value in newMap. Both the values are Map. You can use Map#putAll() method to merge the two maps. It will automatically ignore the already available keys, and add the extra key-value pair.
Now, after resolving the above issue, you should consider changing your data structure. You should create a class say Person, to store all those attributes, and maintain a Map<Integer, Person>, where key will be rollNo.
What you have shown is just what you have. If you could explain some other details like, how and from where did you get those maps, and why would you possibly have the attributes of same person distributed in two different maps, may be we can help you better to formulate the data structure properly. Having a nested Map might be handled if you have small set of data, but if you have larger set of data, you will face difficult in handling them. You should certainly follow Object Oriented Approach.

You should use java object to store complete information.
like
class Student{
int rollNo;
String name;
String height;
String weight;
}
And store your elements like
Map<Integer,Student> map = new HashMap<Integer,Student>();
it will be much easy to merge and store and manage element like this

Related

Store the values without overwriting

I have a Map<String, Integer> e.g.
"aaa", 1
"bbb", 2
"ccc", 3
"aaa", 4
The problem is that the HashMap does not store all key and values, as I've understood, when i try add the last pair ("aaa", 4), it will not be added, instead of this, the value for "aaa" (I mean 1) will be overwritten on 4.
I know, that I could create class, where I could store these pairs, but I need another solution. (without creating a new class)
EDIT ------------------------------------
Actually I have much more pairs, and I do not have uniques String or Integers, I mean that, if even I have two similar pairs they will be stored
A map, by definition, will have distinct keys. If you add a key-value pair and the key already exists, the new key-value pair will overwrite the existing key-value pair.
For your scenario, when you have multiple values against a single key, you can explore the following options
Option 1 : Since your key-value pairs are not unique, it can be stored as list of pairs. For every key-value pair, you can create a pair and insert it into the list.
List<Pair<String, Integer>> data = new ArrayList();
Pair<String, Integer> item = new Pair("abc", 1);
data.add(item);
This option does not give you optimized lookup capabilities that comes with Map.
Option 2. Create a Map<String, List<Integer>>. You'll not be able to do simple put operations on the map anymore, but you will be able to store all the items corresponding to each key without loss of information as well as retrieve them faster.
Create a List:
if (!map.containsKey("aaaa")) {
map.put("aaaa", new ArrayList<Integer>());
}
List<Integer> aaaaValues = map.get("aaaa");
aaaaValues.add(1);
aaaaValues.add(4);
...
If your values are unieque, use them as keys.
You don't have to create class. You can use List<org.apache.commons.lang3.tuple.Pair<String, Integer>>
Also one way, override equals and hashCode where you speak that object is unique only if String and Integer parameter is unique in pair
Map<String, Integer> map = new HashMap<String, Integer>(){
#Override
public boolean equals(Object o)
{
// your realization
}
#Override
public int hashCode()
{
// your realization
}
};

Is it possible to instantiate a Map with a list of keys?

Usually, if I know beforehand all the keys of a map, I instantiate it like this:
List<String> someKeyList = getSomeList();
Map<String, Object> someMap = new HashMap<String, Object>(someKeyList.size());
for (String key : someKeyList) {
someMap.put(key, null);
}
Is there any way to do this directly without needing to iterate through the list? Something to the effect of:
new HashMap<String, Object>(someKeyList)
My first thought was to edit the map's keyset directly, but the operation is not supported. Is there other way I'm overlooking?
You can use Java 8 Streams :
Map<String,Object> someMap =
someKeyList.stream()
.collect(Collectors.toMap(k->k,k->null));
Note that if you want a specific Map implementation, you'll have to use a different toMap method, in which you can specify it.

How to Extract a Map object from another Map object Java

I have the following data structure:
Map<String,Map<String,String>>
I'd like to extract its value (which itself is another string Map) from this complex Map object. I am currently doing it as such:
Map<String, Map<String, String>> map = getStructure(data,format);
Map<String,String> newMap = new LinkedHashMap<String, String>();
for(Entry<String, Map<String,String>> entry : map.entrySet()) {
for (Entry<String, String> value : entry.getValue().entrySet()) {
newMap.put(value.getKey(),value.getValue());
}
}
The above implementation gives me a new Map object with repeating key-value pairs due to the outer foreach loop, it is iterating through. Seems like I'm missing something.
How can I extract the inner Map object from the complex Map object?
Edit:
Addressing AlexWien's comment
Original Data Structure:
The reasoning behind the original data structure is to store a single value for a pair of IDs (ID1 and ID2). ID1 and ID2 may be different. So it is structured as:
Map<String,Map<String,String>> ===> <someValue, <ID1,ID2>>
What I am trying to achieve is to get the entire list of the id pairs (ID1 and ID2) for every someValue. So I can store them in a database to keep track of aeronautical information.
Having an map of maps:
Map<String, Map<String, String>> map
you get the inner map simply by calling get
String key = ...; // TODO
Map<String, String> innerMap = map.get(key);
Update to your edit:
It further seems you need something like a map of pairs:
Map<String, Pair<String, String>> mapOfPairs.
Unfortuneatly java has no Pair class.
So write one yourself:
public class Pair {
String id1;
String id2;
}
and have a
Map<String, Pair> mapOfPairs;

How can I compare two MultiMaps?

I have two Multimaps which have been created from two huge CSV files.
Multimap<String, SomeClassObject> mapOne = ArrayListMultimap.create();
Multimap<String, SomeClassObject> mapTwo = ArrayListMultimap.create();
I have assumed one CSV column to be as a Key and each of the Key has thousands of values associated with it. Data contained within these Multimaps should be same. Now I want to compare the data within these Multimaps and find if any values are different. Here are the two approaches I am thinking of:
Approach One:
Make one big list from the Multimap. This big list will contain a few individual lists. Each of the smaller lists contains a unique value which is the "key" read from Multimap along with its associated values, which will form the rest of that individual list.
ArrayList<Collection<SomeClassObject>> bigList = new ArrayList<Collection<SomeClassObject>>();
Within bigList will be individual small lists A, B, C etc.
I plan on picking individual lists from each bigList of the two files on the basis of checking that individual list from second Multimap contains that "key" element. If it does, then compare both of these lists and find anything that could not be matched.
Approach Two:
Compare both the Multimaps but I am not sure how will that be done.
Which approach should have smaller execution time? I need the operation to be completed in minimum amount of time.
Use Multimaps.filterEntries(Multimap, Predicate).
If you want to get the differences between two Multimaps, it's very easy to write a filter based on containsEntry, and then use the filtering behavior to efficiently find all the elements that don't match. Just build the Predicate based on one map, and then filter the other.
Here's what I mean. Here, I'm using Java 8 lambdas, but you can look at the revision history of this post to see the Java 7 version:
public static void main(String[] args) {
Multimap<String, String> first = ArrayListMultimap.create();
Multimap<String, String> second = ArrayListMultimap.create();
first.put("foo", "foo");
first.put("foo", "bar");
first.put("foo", "baz");
first.put("bar", "foo");
first.put("baz", "bar");
second.put("foo", "foo");
second.put("foo", "bar");
second.put("baz", "baz");
second.put("bar", "foo");
second.put("baz", "bar");
Multimap<String, String> firstSecondDifference =
Multimaps.filterEntries(first, e -> !second.containsEntry(e.getKey(), e.getValue()));
Multimap<String, String> secondFirstDifference =
Multimaps.filterEntries(second, e -> !first.containsEntry(e.getKey(), e.getValue()));
System.out.println(firstSecondDifference);
System.out.println(secondFirstDifference);
}
Output is the element that is not in the other list, in this contrived example:
{foo=[baz]}
{baz=[baz]}
These multimaps will be empty if the maps match.
In Java 7, you can create the predicate manually, using something like this:
public static class FilterPredicate<K, V> implements Predicate<Map.Entry<K, V>> {
private final Multimap<K, V> filterAgainst;
public FilterPredicate(Multimap<K, V> filterAgainst) {
this.filterAgainst = filterAgainst;
}
#Override
public boolean apply(Entry<K, V> arg0) {
return !filterAgainst.containsEntry(arg0.getKey(), arg0.getValue());
}
}
Use it as an argument to Multimaps.filterEntries() like this:
Multimap<String, String> firstSecondDifference =
Multimaps.filterEntries(first, new FilterPredicate(second));
Multimap<String, String> secondFirstDifference =
Multimaps.filterEntries(second, new FilterPredicate(first));
Otherwise, the code is the same (with the same result) as the Java 8 version above.
From the ArrayListMultimap.equals doc:
Compares the specified object to this multimap for equality.
Two ListMultimap instances are equal if, for each key, they contain the same values in the same order. If the value orderings disagree, the multimaps will not be considered equal.
So just do mapOne.equals(mapTwo). You won't have a better execution time by trying to do it yourself.

HashMap<String, Integer> Search for part of an key? [duplicate]

This question already has answers here:
Partial search in HashMap
(5 answers)
Closed 6 years ago.
I am currently using HashMap<String, Integer> which is filled with keys of type String which are all, let's say, 5 chars long. How can I search for an specific key of 4 chars or less, which is part and at the beginning of some other keys and get all hits as a collection of <Key, Value>?
Iterate is your only option unless you create a custom data structure:
for (Entry<String, Integer> e : map.entrySet()) {
if (e.getKey().startsWith("xxxx")) {
//add to my result list
}
}
If you need something more time efficient then you'd need an implementation of map where you are tracking these partial keys.
It seems like a use case for TreeMap rather than HashMap. The difference is that TreeMap preserves order. So you can find your partial match much quicker. You don't have to go through the whole map.
Check this question Partial search in HashMap
You cannot do this via HashMap, you should write your own implementation for Map for implementing string length based searching in a map.
Map<String, Integer> result = new HashMap<String, Integer>;
for(String key : yourMap.keySet()) {
if(key.length() == 4){
result.put(key, yourMap.get(key);
}
}
After executing this code you have all key/value pairs with 4 letter keys in result.
Set<Entry<String, Integer>> s1 = map.entrySet();
for (Entry<String, Integer> entry : s1) {
if(entry.getKey().length == 4)
//add it to a map;
}
First get the entry set to your hashmap. Iterate through the set and check the length of each key and add it to a map or use it as u want it.
With HashMap<String, Integer> you can only go through keySet() and do contains() for String keys and your pattern.
As has been noted, there isn't a terribly efficient* way to do it with the datastructure you have specified. However, if you add an additional Map<Integer, List<String>> to keep track of the mapping from string length to the list of all keys with that length, then you will be able to do this very efficiently.
*Using just the Map<String, Integer>, you would need to iterate through the entire capacity of the larger map, whereas adding this supplemental datastructure would impose an O(1) lookup (assuming you used a HashMap) followed by iteration through just the result set, which is the fastest possible outcome.
You can try this approach:
public Map<String,Integer> filterMap(Map<String, Integer> inputMap){
Map<String, Integer> resultHashMap = new HashMap<String, Integer>();
for (String key : inputMap.keySet()) {
if(key.length()==5){
resultHashMap.put(key,inputMap.get(key));
}
}
return resultHashMap;
}

Categories

Resources