How to convert two arrays into one map<k,v> - java

I have two Arrays,
String[] stageIdList =[V0S186,V0S191,V75S0,V76S0,V0S200,V78S0,V130A0,V0A203];
String[] stageNameList = [Src_DRI_JFP_MISLOG_sf,Tfm_DRI_JFP_MISLOG,Tgt_DRI_JFP_MISLOG,Tgt_A_JFP_MISLOG_D_DS,Sequential_File_200,Sequential_File_201, ,\(20)];
They are in keys: values combination. How do I find equivalent value for a particular key when called?
Will Hashmap be useful in this case? If yes, how do I make for two lists?
PS. I am new to java

I think you want to get some value from StageIdList by value in StageNameList.
You may create
Map<String,String> map = new HashMap<>
for(int i=0;i<stageNameList.size){
map.put(name,stageIdList.get(i));
}
And get value by key:
map.get(key);
key - your name from stageNameList

Would you mind telling more about the question?
1) If you want to do something like:
Give you a stageID, you should return the stageName.
Then you only need one hashmap, where the stageID is the key and the stageName is the value. The solution is similar to Артем К's answer. Though there should be a ++i in the for loop and stageNameList.length and stageIDList[i] as the stageNameList is actually an array.
2) However, if you want to do a two-direction mapping like this:
Give you a stageID, you should return the stageName. AND if give you a stageName, you should return the stageID.
You may need to create two hashmaps. Or you need to do a entrySet to iterate, etc.

Related

Is there an efficient way of checking if HashMap contains keys that map to the same value?

I basically need to know if my HashMap has different keys that map to the same value. I was wondering if there is a way other than checking each keys value against all other values in the map.
Update:
Just some more information that will hopefully clarify what I'm trying to accomplish. Consider a String "azza". Say that I'm iterating over this String and storing each character as a key, and it's corresponding value is some other String. Let's say I eventually get to the last occurrence of 'a' and the value is already be in the map.This would be fine if the key corresponding with the value that is already in the map is also 'a'. My issue occurs when 'a' and 'z' both map to the same value. Only if different keys map to the same value.
Sure, the fastest to both code and execute is:
boolean hasDupeValues = new HashSet<>(map.values()).size() != map.size();
which executes in O(n) time.
Sets don't allow duplicates, so the set will be smaller than the values list if there are dupes.
Very similar to EJP's and Bohemian's answer above but with streams:
boolean hasDupeValues = map.values().stream().distinct().count() != map.size();
You could create a HashMap that maps values to lists of keys. This would take more space and require (slightly) more complex code, but with the benefit of greatly higher efficiency (amortized O(1) vs. O(n) for the method of just looping all values).
For example, say you currently have HashMap<Key, Value> map1, and you want to know which keys have the same value. You create another map, HashMap<Value, List<Key>> map2.
Then you just modify map1 and map2 together.
map1.put(key, value);
if(!map2.containsKey(value)) {
map2.put(value, new ArrayList<Key>);
}
map2.get(value).add(key);
Then to get all keys that map to value, you just do map2.get(value).
If you need to put/remove in many different places, to make sure that you don't forget to use map2 you could create your own data structure (i.e. a separate class) that contains 2 maps and implement put/remove/get/etc. for that.
Edit: I may have misunderstood the question. If you don't need an actual list of keys, just a simple "yes/no" answer to "does the map already contain this value?", and you want something better than O(n), you could keep a separate HashMap<Value, Integer> that simply counts up how many times the value occurs in the map. This would take considerably less space than a map of lists.
You can check whether a map contains a value already by calling map.values().contains(value). This is not as efficient as looking up a key in the map, but still, it's O(n), and you don't need to create a new set just in order to count its elements.
However, what you seem to need is a BiMap. There is no such thing in the Java standard library, but you can build one relatively easily by using two HashMaps: one which maps keys to values and one which maps values to keys. Every time you map a key to a value, you can then check in amortized O(1) whether the value already is mapped to, and if it isn't, map the key to the value in the one map and the value to the key in the other.
If it is an option to create a new dependency for your project, some third-party libraries contain ready-made bimaps, such as Guava (BiMap) and Apache Commons (BidiMap).
You could iterate over the keys and save the current value in the Set.
But, before inserting that value in a Set, check if the Set already contains that value.
If this is true, it means that a previous key already contains the same value.
Map<Integer, String> map = new HashMap<>();
Set<String> values = new HashSet<>();
Set<Integter> keysWithSameValue = new HashSet<>();
for(Integer key : map.keySet()) {
if(values.contains(map.get(key))) {
keysWithSameValue.add(key);
}
values.add(map.get(key));
}

Java- Adding unique values to Hashmap

ok,
here is my issue....I have a List<short>letterList which has for example: "1,2,3,4,5,6,7,8,9,10"
What Im doing is Im iterating over this list then passing the value into another method which returns a value:
so:
string value = null;
for(Short foo : letterList)
{
value = getSomeValue(foo) //returns a letter A or B or C
}
What Im trying to do is get a hashmap to look something like this:
key: a, value 1,5,7
key b, value: 2,3,4
key c, value: 6,8,9,10
not these values specifically, but you get my point
Im not sure how to do this I have tried creating a map with a <set<string>, List<short>
any suggestions would be appreciated
HashMap<Character, List<Short>> map
My understanding was you were looking for a simple way to store a list of values with a character? If so, use that above.
If you want to sort by letter (for easy printing out) use the following:
TreeMap<Character, List<Short>> map
You can get and of the values by using map.get('A') and using your standard methods to iterate through or get a certain value from the associated list.
Java has no built-in MultiMap, but you can either simulate a multimap (Map<String, List<Short>>) or try out Guava for example: https://code.google.com/p/guava-libraries/
Map<String, List<Short>>
The key (String) will be unique. The List<> will be able to hold a list of shorts.
If you want to make sure the numbers are unique as well as the keys, then use a Set instead of a list.
Remember to initialize the lists you put in the map (getting a key like "A" for the first time will return null, so check if it's null and if it is then create a List, put your value into it, and put the list into the map).
Not knowing your complete use case, I would suggest having a different look at your data structure organization. e.g.
Map<Integer, String> map = new HashMap<Integer, String>();
Where the keys are 1,2....10 as in your example and the values are
1 -> a
2 -> b
3 -> b
etc.
To get your original "list" you can use -
Set<Integer> numbers = map.keySet();

Nested Hashmap updates all the values for all the keys instead the one I want to change

I have a hashmap that contains 10 children hashmap, each of these child hashmap 5 keys mapping to a String array. When I want to update a value for a specific key from a children hashmap, all the keys get updated instead; not only that, but also all the children hashmap get updated as well. This code illustrate what I'm doing.
HashMap<String, HashMap<String, String[]>> parentMap = new HashMap<String, HashMap<String, String[]>>();
for(String x : someArray){ // Adds 10 children hashmaps to parentMap
parentMap.put(x,new HashMap<String, String[]>());
for(String y : someOtherArray){ // Creates 5 keys for each of the children hashmaps
parentMap.get(x).put(y,stringArray);
}
}
parentMap.get(someKey).put(someOtherKey,modifiedArray); // This updates the entry I want to update.
When I update with that last instruction, I want to update specifically that key, however everything gets updated instead, all the keys for all the children hashmaps are updated instead the one I want.
Hopefully it makes sense, I'm not sure if this is the correct approach for this but I've been looking online for any tips on doing something similar without any luck. I'm not good at all with Java, if I can achieve the same result with something simpler, it will be welcome, note that I can't use a List or something like that, since it uses int indexes, I need to reference to my objects using a string (like a dictionary on python).
That is because you initialize all maps to contain stringArray, i.e., the same array.
This is why changing one of them, will change all of them.
If you want each key in each inner map to point to different copies of the array, you need to do something like
...
parentMap.get(x).put(y, Arrays.copyOf(stringArray, stringArray.length));
^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^
...
(You could also use for instance clone or create new arrays manually each time you need a new copy.)
#aioobe explained the reason.
Here is the solution. You have to create copy of initial array every time you put it into your map:
String[] tmpArr = new String[stringArray.length];
arraycopy(stringArr, 0, tmpArr, 0, stringArray.length);
parentMap.get(x).put(y,stringArray);

what is the difference between these two object initialization in java?

If i use:
HashMap<String, Integer> test = new HashMap<String, Integer>();
Or i use:
HashMap test = new HashMap();
Is there any difference on further methods that i can apply on test object. like test.put(), test.get() etc if initialized differently??
Also if i put something in test object e.g like:
test.put("One", new Integer(5));
test.put("Two", new Integer(4));
test.put("Three", new Integer(3));
and display it as:
Set set = tokens.entrySet();
Iterator ik = test.iterator();
while(ik.hasNext()){
Map.Entry me = (Map.Entry)ik.next();
System.out.println(me.getKey() + " : " + me.getValue() );
The result is not sorted, restul is:
Three: 3
One: 5
Two: 1
What rule it does follow?? Is this normal behavior for the output to be randomly displayed??
In the first case Hashmap keys must be Strings and values must be Integers. The compiler will perform the respective type checking. In the second case any kind of objects can be used.
This is completely normal that your HashMap entries are printed in random order. If you want to preserve the order use LinkedHashMap instead.
In first example you can only put Strings as keys and Integers as values, but in second example you can put anything to the map and the compiler can't help you to get type safety.
Read more about how Java Generics works.
Yes, you'll get "random" iteration order when using HashMap. If you need a Map implementation with predictable iteration order, check out LinkedHashMap.
In the first case, key must be String and value must be Integer.
In the second case, key and value can be object of anytype.
HashMap and HashSet does not guarantee the insertion order. If you want it to remain in the order at which you insert the value, try LinkedHashMap. Much clearer was answered in previous StackOverflow question here
I think that depends on your usage ,
if you need a compiler to allow you to add only String as Key and Integer as value , then you need to specify both parameters type,
otherwise if you need to pass anything without any restriction then use the second one.

Java queue and multi-dimension array

First of all, this is my code (just started learning java):
Queue<String> qe = new LinkedList<String>();
qe.add("b");
qe.add("a");
qe.add("c");
qe.add("d");
qe.add("e");
My question:
Is it possible to add element to the queue with two values, like:
qe.add("a","1"); // where 1 is integer
So, that I know element "a" have value 1. If I want to add a number let say "2" to element a, I will have like a => 3.
If this cant be done, what else in java classes that can handle this? I tried to use multi-dimention array, but its kinda hard to do the queue, like pop, push etc. (Maybe I am wrong)
How to call specific element in the queue? Like, call element a, to check its value.
[Note]
Please don't give me links that ask me to read java docs. I was reading, and I still dont get it. The reason why I ask here is because, I know I can find the answer faster and easier.
You'd want to combine a Queue<K> with a Map<K,V>:
Put the keys (e.g. "a", "b") into the Queue<K>
Assign the mapping of the keys to values (e.g. "a"=>3) in the Map<K,V>
I think you're asking for a dictionary type in Java.
Map<String, Integer> map = new HashMap<String, Integer>();
map.put("a", 1);
map.put("b", 2);
You can then access them by key - in this case the String you choose as the key.
int value = map.get("a");
Value in this case will return 1.
Is that what you want?
You want to use a HashMap instead of LinkedList. HashMap is a dictionary-like structure that allows you to create associations, for instance a=>1.
Check out JavaDocs for HashMap to get a grasp how to use it:-).
I think what you are asking for is LinkedHashMap which is a combination of a Queue and a HashMap. While you are able to store the key and value pairs, it would also remember the order like Queue does. The only thing is you'd have to use an iterator since there is no poll() method, however you can visit each element in the order that they were added.

Categories

Resources