How do I reverse a map with a Set<Integer> included? - java

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);
}
}

Related

Create or Update key value pairs in both maps

I've map of key value pairs with each value being a map of key value pairs.
Something like
Map<String, Map<String, Integer> outMap = new HashMap<>();
Map<String, Integer> inMap = new HashMap<>();
inMap.put("i11", 111);
inMap.put("i21", 121);
outMap.put("o1", inMap);
How would I handle the entry where I can create/update at both levels of the map using java 8 ?
Input would be outer key/inner key and value. So we should we able to add a new entry is it doesn't exist in outer map. If the entry exists in outer map then insert the new entry in inner map if it doesn't exist else update the inner map with new value.
What you want to achieve can be done with this single line of code:
outerMap.computeIfAbsent(outerKey, k -> new HashMap<>()).put(innerKey, value)
But without these methods, you can achieve the same with just get() and put():
Map<String, Integer> innerMap = outerMap.get(outerKey);
if (innerMap == null) {
innerMap = new HashMap<>();
outerMap.put(outerKey, innerMap);
}
innerMap.put(innerKey, value);
HOW TO UPDATE THE SINGLE-VALUE AND MULTIPLE VALUES AT THE SAME TIME SIMULTANEOUSLY IN TWO MAPS
NTOE:
givenMap.computIfAbsent(k,Funtion) -> if key in given map is null or absent, then compute the value using funtion and add into the given map
Map<String, Map<String, Integer>> outMap = new HashMap<>();
Map<String, Integer> inMap = new HashMap<>();
inMap.put("i11", 111);
inMap.put("i21", 121);
outMap.put("o1", inMap);
System.out.println(outMap.toString());
System.out.println(inMap.toString());
OUTPUT BEFORE UPDATING:
{o1={i11=111, i21=121}}
{i11=111, i21=121}
//If you want to add one value in the inner hashmap you created:
outMap.computeIfAbsent("newHashMapKey",k -> new HashMap<>()).put("Arpan",2345);
// if you want to add more than 1 value at a time in the inner hashmap
outMap.computeIfAbsent("newHashMapKey2",k -> new HashMap<>()).putAll(new HashMap<String, Integer>(){{
put("One", 1);
put("Two", 2);
put("Three", 3);
}});
System.out.println(outMap.toString());
System.out.println(inMap.toString());
OUTPUT AFTER UPDATING BOTH MAPS AT THE SAME TIME
{o1={i11=111, i21=121}, newHashMapKey2={Two=2, Three=3, One=1}, newHashMapKey={Arpan=2345}}
{i11=111, i21=121}

Merge maps and make values as array

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);
}
}

Add multple maps to list in Java

I have multiple maps (like 100 or more). I want to put them to list like this:
ArrayList<HashMap> mapsList = new ArryaList(Arrays.asList(map1, map2, map3 ..., map100);
is there a way to put all this in here in one loop to avoid writing the same name one hundred times changing only number in it?
#EDIT
I have this map like this:
HashMap<String, Integer> map1 = new HashMap<>();
map1.put("x", 47);
...
nextmap here...
Use a method to generate a map, insert the value and add it in the List.
public Map<String, Integer> newMap(Values... values){
Map<String, integer> map = new HashMap<>();
for(Values v : values){
map.put(v.getKey(), v.getValue());
}
list.add(map);
return map;
}
Where Values hold both key and value
class Values{
String key;
Integer value;
public Values(String key, Integer value){
...
}
//getters;
}
That way, you don't need to play with map1, map2, map3, .. but simply call that method.
newMap(new Values("x", 47), new Values("y", 12));
newMap(new Values("x", 4));
...

Identify the Key-Value pair having duplicate values

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]}

Read HashMap<String, HashMap<Double, Integer>

There is a HashMap:
HashMap aircraftHandling = new HashMap<String, HashMap<Double, Integer>>();
This HashMap contains the following entries:
HashMap<"M", HashMap<1.22, 200>>();
HashMap<"M", HashMap<5.62, 300>>();
HashMap<"L", HashMap<10.11, 900>>();
I need to get entries for the key "M", i.e. HashMap<1.22, 200> and HashMap<5.62, 300>. I do this in the following way:
HashMap lines = (HashMap<Double, Integer>) aircraftHandling.get("M");
The question is how to get Double and Integer, ie (1.22, 200) and (5.62, 300), into two separate variables?
for (int i=0; i<lines.size(); i++)
{
//doubleValue = [i]???
//integerValue = [i]???
}
You can use an enhanced for loop just to read elements :
for (Map.Entry<Double, Integer> entry : lines.entrySet()) {
Double key = entry.getKey();
Integer value = entry.getValue();
}
This HashMap contains the following entries:
HashMap<"M", HashMap<1.22, 200>>();
HashMap<"M", HashMap<5.62, 300>>();
HashMap<"L", HashMap<10.11, 900>>();
I need to get entries for the key "M", i.e. HashMap<1.22, 200> and HashMap<5.62, 300>. I do this in the following way:
Not considering the syntax used , since the key is a String , the second time you try to put() a value in the Map using a String key which already exists in Map the new value will override the old value.
This is how you would extract a key-value pair of the HashMap by iterating over a keyset:
Iterator<Double> it= lines.keySet().iterator();
while (it.hasNext()) {
Double key= it.next();
Integer value= lines.get(key);
}
On the side note, I don't know if this is an error, or just a bad representation of your data:
HashMap<"M", HashMap<1.22, 200>>();
HashMap<"M", HashMap<5.62, 300>>();
But if it is how it looks, this is impossible. A Map can have a single value for a single key! That means, if you put some value for a key "M" and you do it again for the same key, the latter will overwrite the previous value. What you should do is:
//get the inner map for "M"
HashMap<Double, Integer> innerMap= aircraftHandling.get("M");
if (innerMap == null) {
//if it does not exist instantiate it
innerMap= new HashMap<Double, Integer>();
aircraftHandling.put("M", innerMap);
}
and now, in the innerMap you add other values, e.g.:
innerMap.put(1.22, 200);
innerMap.put(5.62, 300);
Try maybe this way
Map<Double, Integer> lines = (HashMap<Double, Integer>) aircraftHandling.get("M");
// ^add this generic types here so you wont have to cast them later with getters
for (Map.Entry<Double, Integer> entry:lines.entrySet()){
Double key = entry.getKey();
Integer value = entry.getValue();
}
Here you have it:
HashMap<String, HashMap<Double, Integer>> aircraftHandling = new HashMap<String, HashMap<Double, Integer>>();
HashMap<Double, Integer> subMap1 = new HashMap<Double, Integer>();
subMap1.put(1.22, 200);
HashMap<Double, Integer> subMap2 = new HashMap<Double, Integer>();
subMap1.put(5.62, 300);
aircraftHandling.put("M", subMap1);
aircraftHandling.put("L", subMap2);
HashMap<Double, Integer> lines = aircraftHandling.get("M");
for (Entry<Double, Integer> set : lines.entrySet()) {
Double doubleValue = set.getKey();
Integer integerValue = set.getValue();
}
First, Map can't have duplicate key. If you insert duplicate key then previous one will disappear. You can use following code to separate key and value:
HashMap lines = (HashMap<Double, Integer>) aircraftHandling.get("M");
for(Map.Entry<Double, Integer> entry: lines ){
doubleValue = entry.getKey();
integerValue =entry.getValue();
}
with a foreach loop and method HashMap.entrySet() :
HashMap<Double, Integer> map=...
for(Entry<Double,Integer> entry : map.entrySet()){
Double d = entry.getKey();
Integer i = entry.getValue();
}
You cannot have 2 values for the key M. I hope you've taken care of that while putting the values. You should have put one hashmap for the value M.
You simply need to fetch the hashmap corresponding to key M
HashMap lines = (HashMap<Double, Integer>) aircraftHandling.get("M");
And then iterate over all entries in this map
Iterator it = lines.entrySet().iterator();
while (it.hasNext()) {
Map.Entry pairs = (Map.Entry)it.next();
double d = pairs.getKey().doubleValue();
int i = pairs.getValue().intValue();
}
EDIT - Had answered from my mobile so missed a few details. Adding them now.

Categories

Resources