Read HashMap<String, HashMap<Double, Integer> - java

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.

Related

How can i convert Map of Strings and Object to a Map of Strings and List

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

Map.keySet() read sequence?

I have Map<String, List<String>> map now, putting two values inside Map, now when read keyset from map gives in different sequence in different device.
private Map<String, List<String>> map = new HashMap<>();
map.put("First", new ArrayList<String>());
map.put("Second", new ArrayList<String>());
Now, Read keys from this map.
Set<String> keys = map.keySet();
for (int i = 0; i < map.size(); i++) {
Log.d("key", keys.toArray()[i].toString());
}
OUTPUT IN OREO 8.0
D/Key : First
D/Key : Second
OUTPUT in BELOW 8.0
D/Key : Second
D/Key : First
I got a solution until we defined Set as SortedSet ,we getting key sequence in different order.
SortedSet<String> keys = new TreeSet<>(map.keySet());
for (int i = 0; i < map.size(); i++) {
Log.d("key", keys.toArray()[i].toString());
}
You're using the HashMap as the data structure. As in HashMap, the order of insertion is not maintained thus you're getting a random order of the keys. If you want to maintain the order of insertion, simply use a LinkedHashMap. The order in which you put the data is maintained and simply you can iterate over it.
Sample code for LinkedHashMap:
Map<String, String> map = new LinkedHashMap<>();
map.put("key1", "value2");
map.put("key3", "value4");
map.put("key5", "value6");
map.put("key7", "value8");
Set<String> keySet = map.keySet();
for(String st: keySet){
System.out.println(st);
}
for(Map.Entry<String, String> entry : map.entrySet()){
System.out.println(entry.getKey() + " " + entry.getValue());
}
Output:
key1
key3
key5
key7
key1 value2
key3 value4
key5 value6
key7 value8
It has nothing to do with the android OS. The resulting Set of HashMap has no order. However there are Sets with an order e.g. TreeSet.

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

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

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

Traverse values of Hash map key an value in decreasing order or increasing order?

I am trying to traverse a Hash map in decreasing order or in increasing order but I am not getting the proper output.
Here is my map:
Hashmap<String Integer> hm= new Hashmap<String,Integer>();
Here are my values:
Key Value
Hi 4
kumar 1
Hello 1
vivek 3
I am trying something like:
List<Integer> ValueList = new ArrayList<Integer>(hm.values());
ArrayList<String> keyList = new ArrayList<String>(hm.keySet());
Collections.sort(ValueList);
Collections.reverse(keyList);
Collections.reverse(ValueList);
and I want this something like:
Key Value
kumar 1
Hello 1
vivek 3
Hi 4
I recommend using the Apache Commons Collections ListOrderedMap. Here's the solution:
//Populate the map
Map<String, Integer> map = new HashMap<>();
map.put("Hi", 4);
map.put("kumar", 1);
map.put("Hello", 1);
map.put("vivek", 3);
//Sort the values
List<Integer> values = new ArrayList<Integer>(map.values());
Collections.sort(values);
int size = values.size();
Set<Entry<String, Integer>> entries = map.entrySet();
//Create a new ordered map
ListOrderedMap<String, Integer> orderedMap;
orderedMap = ListOrderedMap.listOrderedMap(new HashMap<String, Integer>(map));
for (int i = 0; i < size; i++) {
Integer value = values.get(i);
Iterator<Entry<String, Integer>> iter = entries.iterator();
while (iter.hasNext()) {
Entry<String, Integer> entry = iter.next();
if (value.equals(entry.getValue())) {
//Put all values at index i that match the value
orderedMap.put(i, entry.getKey(), value);
}
}
}
//Print the orderedMap key/value pairs
entries = orderedMap.entrySet();
for (Entry<String, Integer> entry : entries) {
final String key = entry.getKey();
final Integer value = entry.getValue();
System.out.println("key = " + key + ", value = " + value);
}
Output:
key = Hello, value = 1
key = kumar, value = 1
key = vivek, value = 3
key = Hi, value = 4
You can view a Map as a set of entries, where each entry has a key and a value. So what you want is a sorted list of entries. You can't just sort keys or values, as you would lose the association between the key and the value:
List<Map.Entry<String, Integer>> entries = new ArrayList<>(map.entrySet());
entries.sort(Comparator.comparing(Map.Entry::getValue));
If you need to access these values often, you can avoid the sort by using a TreeMap object.
http://docs.oracle.com/javase/8/docs/api/java/util/TreeMap.html
This special Map can be used like a normal HashMap with the additional feature that it will sort your keys automatically using their Comparable, Equals and Hash methods (which you have to override)
If you define your own Key Class, you can make it so it will sort your values automatically.
If you don't need this performance boost, extracting the values then sorting them with Collections.sort works well too.

Categories

Resources