I have a multimap like below:
{20014=[13123], 20013=[45451, 13123]}
where the keys and values are in String
If there is any duplicate in the value from other key, I have to print that key-value pair. In this case, it will be Key-20013,Value-13123.
How to achieve this?
I checked this link but not getting how to get the duplicate pair.
It could be done like this:
// Initialize my multimap
Multimap<String, String> multimap = ArrayListMultimap.create();
multimap.put("20014", "13123");
multimap.put("20013", "45451");
multimap.put("20013", "13123");
// Set in which we store the values to know if they exist already
Set<String> allValues = new HashSet<>();
// Convert the multimap into a Map
Map<String, Collection<String>> map = multimap.asMap();
// Iterate over the existing entries
for (Map.Entry<String, Collection<String>> entry : map.entrySet()) {
String key = entry.getKey();
Collection<String> values = entry.getValue();
// Iterate over the existing values for a given key
for (String value : values) {
// Check if the value has already been defined if so print a log message
if (!allValues.add(value)) {
System.out.println(String.format("Key-%s,Value-%s", key, value));
}
}
}
Output:
Key-20013,Value-13123
You can invert your multimap and, viewed as a map, iterate through its entries:
Multimap<String, String> inverse = Multimaps.invertFrom(multimap, HashMultimap.create());
for (Map.Entry<String, Collection<String>> entry : inverse.asMap().entrySet()) {
String value = entry.getKey();
Iterator<String> keysIterator = entry.getValue().iterator();
assert keysIterator.hasNext() : "there is always at least one key";
keysIterator.next(); // skip first key
while (keysIterator.hasNext()) { // each additional key is a duplicate
String key = keysIterator.next();
System.out.println(String.format("Key-%s,Value-%s", key, value));
}
}
Output:
Key-20013,Value-13123
If you are using an ImmutableMultimap then instead of Multimaps.invertFrom(Multimap, M) you can simply use ImmutableMultimap.inverse():
ImmutableMultimap<String, String> inverse = multimap.inverse();
If you simply want a map of duplicated values to their respective keys then you can use Maps.filterValues(Map, Predicate):
Map<String, Collection<String>> keysByDuplicatedValue = Maps.filterValues(inverse.asMap(),
keys -> keys.size() > 1);
Which will give you a map like below:
{13123=[20014, 20013]}
Related
I am using a multimap like this
Multimap<String, MyObject> tasksMap = ArrayListMultimap.create();
Where there can be multiple items for the same key, get the List value for every key in the map?
.asMap() lets you get a map and you can then iterate over its .entrySet().
Something like
for (Entry<String, Collection<MyObject>> e : tasksMap.asMap().entrySet()) {
String key = e.getKey();
Collection<MyObject> values = e.getValue();
...
}
Just use get method to get all values for a key
List<MyObject> values = tasksMap.get(key);
or use values to get all values for every key in map
Collection<List<MyObject>> values = tasksMap.values();
or entries to get all entries
Collection<Map.Entry<String, List<MyObject>>> entries = tasksMap.entries()
I have method that should return Map<Strings, List<String>> but in the mean time my method gives me a Map<Strings, Object>, I want to transfer the values of object into a List of Strings.
Here is the current code:
#SuppressWarnings("unchecked")
static Map<String, List<String>> getQueryParameters(JsonObject inputJsonObject) {
JsonArray parameters = inputJsonObject.getJsonArray("parameters");
Optional<JsonObject> queryParameters = parameters.stream().
filter(JsonObject.class::isInstance).
map(JsonObject.class::cast).
filter(jsonObject -> jsonObject.getJsonObject("queryParameters") != null).
map(item -> item.getJsonObject("queryParameters")).findFirst();
Map<String, Object> paramMap = queryParameters.get().getMap();
paramMap contains key and value , values could be an arrays of integers
so I want to put them into the map below:
Map<String, List<String>> mystore = new LinkedHashMap<String, List<String>>();
My solution is this which did not work correctly
Map<String, List<String>> mystore = new LinkedHashMap<String, List<String>>();
Map<String, Object> paramMap = queryParameters.get().getMap();
Iterator it = paramMap.entrySet().iterator();
while (it.hasNext()) {
String key = it.next().toString();
if (!mystore.containsKey(key)) ;
mystore.put(key, new LinkedList<String>());
mystore.get(key).add(it.next().toString());
}
I was a key holding another key as value and is just a mix up , any suggestions?
After debuging what happens i see that mystore holds both "key and value" together as a key and value it hold the next "key and value as value
Should be something like this:
while (it.hasNext()) {
Map.Entry<String, Object> next = iterator.next();
String key = next.getKey();
Object value = next.getValue();
if (!mystore.containsKey(key)) mystore.put(key, new LinkedList<String>());
mystore.get(key).add(value.toString());
}
I'm not writing a program for you, but instead help you in finding a problem. You are confused with Entry. If you are using IDE, you should solve it easier. Look for this line :
String key = it.next().toString();
Entry has a K,V pair. The iterator returns an EntrySet and thus usage to get key is it.next().getKey() and it.next().getValue()
Now that you have a correct key, please go on debugging. Instead of putting and getting and manipulating in below lines of your code. Put with correct value instead?
Yours:
mystore.put(key, new LinkedList<String>());
mystore.get(key).add(it.next().toString());
What about?:
Entry entry = it.next();
//Get key and value here. DO coding using Entry's methods
List<String> ll = new LinkedList<String>();
ll.add(value)
mystore.put(key, ll);
Tip: Always have the Javadoc or reference documentation handy for knowing more. That's how you learn the language. Refer:https://docs.oracle.com/javase/7/docs/api/java/util/Map.Entry.html
public class MapCheck {
public static void main(String[] args) {
Map<String, String> data = new HashMap<String, String>();
data.put("John", "Taxi Driver");
data.put("Mark", "Professional Killer");
Map<String, String> data1 = new HashMap<String, String>();
data1.put("John", "Driver");
data1.put("Mark", "Murderer");
Map<String, String> data3 = new HashMap<String, String>();
data3.putAll(data);
data3.putAll(data1);
System.out.println(data3);
}
}
I have few maps which contains same key, their values are different. I want to merge them. But when I merge them with the usual putAll() it gives me only the value of the key which was inserted latest.
Output from above code is {John=Driver, Mark=Murderer}
Is there a method which will get me all the values associated with the key and give me as a array like
{John=[Taxi Driver, Driver], Mark=[Professional Killer, Murderer]}
You can produce a Map<String, List<String>> quite easily with Java 8 Streams:
Map<String, List<String>>
merged =
Stream.of(data,data1) // create a Stream<Map<String,String> of all Maps
.flatMap(map->map.entrySet().stream()) // map all the entries of all the
// Maps into a
// Stream<Map.Entry<String,String>>
.collect(Collectors.groupingBy(Map.Entry::getKey, // group entries by key
Collectors.mapping(Map.Entry::getValue,
Collectors.toList())));
The output Map:
{John=[Taxi Driver, Driver], Mark=[Professional Killer, Murderer]}
Something like this?
void add(String key, String value, Map<String,List<String>> map) {
List<String> list = map.get(key);
if (list == null) {
list = new ArrayList<>();
map.put(key, list);
}
list.add(value);
}
the data structure Multimap may be the best choice. The implementation in guava is highly recommended.
https://github.com/google/guava/wiki/NewCollectionTypesExplained#multimap
You may want to create Map<String, <ArrayList<String>>. That way you can store multiple values that are associated with one key.
You may consider creating method that provides storing multiple values associated to unique key in specified map:
public static void add(String key, String value, Map<String, List<String>> map) {
// Here you create a refeREnce to instance of the list storing values associated with given key:
List<String> listOfValues = map.get(key);
// If given key was already present in the map...
if(listOfValues != null) {
// Add given value to list of values associated with given key:
listOfValues.add(value);
// If given key wasn't present in the map...
} else {
// Initialize an ArrayList that will store given value in the map:
listOfValues = new ArrayList<>();
// Put new entry into the given map (given key and to-be-filled list of values:
map.put(key, listOfValues);
// Put given value to the list of values associated with given key
listOfValues.add(value);
}
}
For instance if I have a map with integer and strings:
Map<Integer, String> myMap = new HashMap<Integer, String>();
This map would contain key values of Integers and values of names.
What I am trying to do is make a new map, that copies all the values (names) from theMap and makes them the keys for the new map. Now the tricky part I can't get, is that I want the values of the new map to be the numbers, but if there are multiple numbers that correspond to the same name I want them to be held in an Set.
Example of new map:
Map<String, Set<Integer>> returnMap = new TreeMap<String, Set<Integer>>();
So if "John" corresponds to 1,2,3,4. I would like the new map to contain a key of "John" with a Set containing 1,2,3,4
Google's Guava library has a nice Multimap class which maps keys to multiple values. If you use it, you can take advantage of a host of helper methods:
SetMultimap<String, Integer> returnMap =
Multimaps.invertFrom(Multimaps.forMap(myMap), TreeMultimap.create());
It's not that tricky :)
Map<Integer, String> map = ... //Your map
Map<String, Set<Integer>> reverseMap = new TreeMap<String, Set<Integer>>();
for(Map.Entry<Integer, String> entry : map.entrySet()) {
Integer key = entry.getKey();
String value = entry.getValue();
Set<Integer> set;
if(reverseMap.containsKey(value)) {
set = reverseMap.get(value);
set.add(key);
} else {
set = new HashSet<Integer>();
set.add(key);
reverseMap.put(value, set);
}
}
Hi I am working with HashMap in java and i have a scenario where i have to compare 2 HashMaps
HashMap1:
Key: BOF Value: SAPF
Key: BOM Value: SAPM
Key: BOL Value: SAPL
HashMap2:
Key: BOF Value: Data1
Key: BOL Value: Data2
And after comparing these two hashmaps my resulting hashmap will contain the Key as a Value of First HashMap1 and Value as a Value of second HashMap2.
HashMap3:
Key: SAPF Value: Data1
Key: SAPL Value: Data2
Just iterate on the keys of HashMap1, and for each key, check if it's present in HashMap2.
If it's present, add the values to HashMap3 :
final Map<String, String> hm1 = new HashMap<String, String>();
hm1.put("BOF", "SAPF");
hm1.put("BOM", "SAPM");
hm1.put("BOL", "SAPL");
final Map<String, String> hm2 = new HashMap<String, String>();
hm2.put("BOF", "Data1");
hm2.put("BOL", "Data2");
final Map<String, String> hm3 = new HashMap<String, String>();
for (final String key : hm1.keySet()) {
if (hm2.containsKey(key)) {
hm3.put(hm1.get(key), hm2.get(key));
}
}
Iterate over the keys of the first map and put the values in your new map, if the second map has a value for the same key.
Map map3 = new HashMap();
for (Object key : map1.keySet()) {
Object value2 = map2.get(key);
if (value2 != null) {
Object value1 = map1.get(key);
map3.put(value1, value2);
}
}
HashMap has an method called entrySet() that returns an object that represents the content of the map as a set of key-value pairs.
public Set<Map.Entry<K,V>> entrySet()
You should iterate through that set using the keys to look up in the second map and then putting the results in the 'result set'.
I assume you have a established that the values in the first set will be unique OR you don't mind that entries might get overwritten in the output.
Notice that the iterator moves through the set in an unspecified order so if there are overwrites this method won't guarantee which values overwrite which other values.
You can use the keySets of both maps to intersect them using:
boolean retainAll(Collection<?> c)
and then iterate using that intersection over the tho maps building your solution.