Hashmap fails to fetch the value for my key - java

I have a text file like the format below
module1.q1=a1
module1.q2=a2
module2.q1=a1
module2.q5=a6
..
..
I have a class objectsHmp which has two String variables to store questions(q1, q2, q3,...) and answers(a1,a2,a3,..). what i'm trying to do is keeping the module id as the key, i want to populate a hashmap with values as arraylist of objects(of objectsHmp). And in turn i'm storing the keys in an arraylist of String.
In the below code snippet,
*l_ext_keys* is an arraylist of String which stores the keys,
*l_extract* is a HashMap>,
*l_temp_array* is an arraylist of object objectsHmp,
while((line=br.readLine()) != null)
{
String[] ss = new String[2];
ss = line.split("=");
String tss = ss[0];
String[] kss = tss.split("\\.");
objectsHmp temp = new objectsHmp(kss[1],ss[1]);
if(!prev.equals(kss[0]))
{
l_ext_keys.add(prev);
l_extract.put(prev,l_temp_array);
l_temp_array.clear();
}
l_temp_array.add(temp);
prev = kss[0];
}
l_extract.put(prev,l_temp_array);
l_ext_keys.add(prev);
l_temp_array.clear();
Problems
The Hashmap is getting populated but it's not having values for some keys present in the l_ext_keys. I tried printing the length of the arraylist and hasmap, but its having a great difference(arraylist with the keys having more values than hashmap).
One possible reason for this difference is some module is repeated.
I dint override any function
Question
What are the possibilities that hashmap couldn't get values for the keys present in the list? Or am I doing some big mistake here?

Its not possible to have a key more than once in a HashMap. Keys must be unique. So you override the old key with your approach right now.
You could use the HashMap as a directory, saving all values for one key in an Array or ArrayList and then define:
HashMap<String, ArrayList<String>> directory = new HashMap<String, ArrayList<String>>();
After that you can retrieve an ArrayList holding the values for q1 with the key q1
EDIT:
Your code is missing some information, but as far as I can see you are putting module1 and so on as the key in your hashmap. You check through if(!prev.equals..) for a new module, but that means only the first occurence of some module is being stored (if your file is sorted). If the list is not sorted, its getting overriden somewhere in the process.
Your whole function seems a bit buggy. :) Also check the code where you work with the temp arrayList, because you always add the question and answer to it. So some questions&answers get even saved with the wrong module. And at the first run of the while loop l_temp_array seems to be empty, so you add module1 with an empty value to the HashMap..

The problem with your code is that it doesn't handle well cases when the module names are not sorted, e.g.
module1.q1=a1
module2.q1=a1
module1.q2=a2
module2.q5=a6
You can add values directly to the hashmap without using temporary lists, like this:
objectsHmp temp = new objectsHmp(kss[1],ss[1]);
ArrayList<objectsHmp> list = l_extract.get(kss[0]);
if(list == null){
list = new ArrayList<objectsHmp>();
l_extract.put(kss[0], list);
}
list.add(temp);
This solution will remove the risks I mentioned in the beginning.
Also, you're not following 100% the Java notation conventions, e.g. method names should have capital first letter; and for variable names the camelCase notation is preferred rather than underscores.

Related

Is there a way to map a set to a string without creating many set instances?

I have a school project that involves recommending a university course to students to study based on four favorite subjects each user enters.
My approach is to use HashMap in Java: HashMap<String, Set<String>>. The course is the simple string, while each set contains the four subjects required for the course.
Each entry should be added manually but in turn it requires many instances of the Set objects for each entry:
Set<String> setA = new HashSet<String>(); // for first pair
Set<String> setB = new HashSet<String>(); // for second pair.
And so on...
For each key/value entry, I want to check/compare the value (set of subjects) with the four subjects entered by the user and if the set contains the entered subjects, the key (course) is added to a matches array.
Does anyone have any idea on how I should go about this?
I have tried working on this. I really need to meet the deadline
What I'm assuming you want is a Map.Entry. You mentioned in your question you want to use a HashMap. To loop through a HashMap's list of values you would do something like this:
for(Map.Entry<Integer, Integer> eachEntry : hashMap.entrySet())
{
int key = eachEntry.getKey();
int value = eachEntry.getValue();
}
In my example it's a hashmap containing Integer key value pairs, but you can change it to the type you want. A quick google search would show how to go through a Set inside of a hashmap. Hope this helps
You can compare values this way , by iterating through the hashMap keys
for(String course: hashMap.keySet()) {
//Convert all the set values to lower case. Also do the same for user entered subjects set.
Set<String> newSet = hashMap.get(course).stream().map(String::toLowerCase).collect(Collectors.toCollection(HashSet::new));
if( newSet.containsAll(userEnteredCourses)) {
matchesArray.add(course);
}
}

Storing an Array in a HashMap as its value

I want to store a Float array as a value of the HashMap.
HashMap<Integer, Float[]> vFeatureHm = new HashMap<Integer, Float[]>();
The float array here contains a specified number of values, for example say 10. How and where do I mention that ? I will be dynamically adding the values into that array. I can use an ArrayList but I'm using this for a matrix kind structure and it is easy for me to just get the value from the index as the values are stored in that order. ArrayList seems to be an overkill in this case for me. Can you suggest how to solve this. For now, I started working with ArrayList, but I want to know if there is a way to use as I mentioned above.
Update: I realized ArrayList will not work for me in my case as I need to place in a particular index. So I have to use either the format mentioned above or use a HashMap which is again a over kill. Any suggestions on using Float as above mentioned ?
You do not need to specify the dimensions of the Float[] array.
That array is an Object like any other value of the vFeatureHm map, so any bounds checking is irrelevant to the HashMap (although of course it can be performed at another part of your code).
Since float is an object, I initialized it like below.
Float[] featureValues = uFeatureHm.get(userid);
if(featureValues == null){
featureValues = new Float[Settings.noOfCommonFeatures];
featureValues[fi-1] = fv;
uFeatureHm.put(userid, featureValues);
}else{
featureValues[fi-1] = fv;
}
Later, I can simply access a feature of particular user as uFeatureHm.get(userid)[featureIndex]

Two ArrayList into a TreeMap

I've been searching StackOverflow for an answer regarding this issue.
Lets say I created two array lists,
arraylist1 holds Strings
arraylist2 holds Integers.
NOTE - I've added things into both of these arraylists. The values at each of the indices are related to the other value.
Meaning. lets say index 1 of arraylist1 = "Name". Index 1 of arraylist2 = 3, they are related in that I want to put things into a TreeMap (for the purpose of sorting by key) so that the treemap puts in the value ("Name", 3).
My problem -
TreeMap<String, Integer> mymap = new TreeMap<String, Integer>();
for(String s : arraylist1) {
for(Integer v : arraylist2) {
mymap.put(s, v);
The problem with this is if I added a bunch of random things for testing,
arraylist1.add("h");
arraylist1.add("i");
arraylist1.add("e");
arraylist2.add(1);
arraylist2.add(3);
arraylist2.add(2);
And I did the for loops, my result would come out to...
Key e Value: 2
Key h Value: 2
Key i Value: 2
Which solves the problem of sorting by key. However, the problem is that only the last value in the Integer arraylist, arraylist2, is being put into the TreeMap.
Don't you want to iterate through both lists at the same time ?
for (int i = 0; i < list.size(); i++) {
map.put(list1.get(i), list2.get(i));
}
As it currently stands, you're iterating over your second map for each key, and inserting the second list's values. Since a map only holds one value per key, your map results in the final value in your second list for each key.
As an aside, if these 2 values are intrinsically linked, perhaps create (or use an existing) Pair object to store these from the outset. The problem with using a standard map is that you can only store one value per key. e.g. you can't store (A,B) and (A,C)
Well fark, I was typing this in your deleted question before you deleted it, but didn't finish til after you deleted it:
I'm not sure if I fully understand your question, but consider:
Creating a Game class that is in charge of the logic of the game.
Creating Player objects that interact with the Game.
When a Player wants to move, he calls Game's move(Piece piece, Position position) method, but with parameters.
Have this method return a boolean, true if the move is valid and false if not...

Implementing a complex method to compare two sets of Strings when groups of one are associated with a third

I have a rather complex method that I need to implement. So please bear with me as I try to describe it in as simple a way as I can.
I'm given a set A of Strings that represent filenames - let's say "abc", "def", and "ghi". I must derive from these names a set B of "associated" filenames for each - let's say "abc_123", "abc_456", and "abc_789" for "abc"; "def_123", "def_456", and "def_789" for "def"; and "ghi_123", "ghi_456", and "ghi_789" for "ghi". This much I can do. However, these associated filenames may have prefixes or suffixes attached to them which are unpredictable strings of characters - so the associated filenames for "abc" might actually be "HELLOabc_123WORLD", "FOOabc_456BAR", and "999abc_789000". (In terms of regular expressions, it's just a matter of putting a * on both sides of the associated filenames I had written above). In short, the associated filenames will look like this:
*<original filename><other piece that I know>*
where the stars indicate any number of random characters (could be 0).
That's the first piece of the puzzle.
Next, I am given another set C of Strings that I am to compare to the set of associated filenames (set B). (In case you're wondering, I'm trying to check if the associated files are in a certain directory, and I have the list of filenames in that directory, set C). If I find all the associated filenames for a certain file in set C, I can go ahead and check off that file from set A. I must go and check each filename in set A, and if all of its associated filenames from set B are found in set C, I can check off that file from set A.
Finally, I must return the filenames from set A that were not checked off (so I'd return nothing if everything was found).
I've been struggling to come up with a way to implement this method. I thought of creating a Map that would map a filename from set A to a List containing all the filenames associated with that filename like so:
Key Value
abc *abc_123*, *abc_456*, *abc_789*
def *def_123*, *def_456*, *def_789*
ghi *ghi_123*, *ghi_456*, *ghi_789*
I could then traverse the elements of this map, and the values of the elements, comparing them to the Strings in set C. And if all Elements of the value (the List) for a given Key are found in set C, I could mark that Key off my list. Any Keys remaining would be returned.
This seems to me like it should work, but the actual mechanics of putting that into code have been very challenging for me. So if you could give me any small suggestions or pointers that would move my thinking in the right direction, I'd appreciate it very much. My implementation language will be Java in case you'd like to give code. Pseudocode is welcomed as well.
I'm not quite sure if I understand your problem correctly, but this is how I imagine it:
List<String> setCStrings = //your set C strings I guess...
for(String aSetCString : setCStrings) {
String pattern = ".*" + filename + "_" + associatedFileName + ".*";
if(aSetCString.matches(pattern)) {
// do what you want with this string that matches the filename and associated file name
}
}
I think you have correctly identified the solution partially to your problem. You will need a Map for sure and essentially your problem boils down to finding if all elements in a given list are present in a set of strings in C. I am not sure about what data structure is holding the set B or C of strings. But I can provide a pseudo code for the rest:
Initialize a HashMap<String, ArrayList>
for each string in set B
if it matches the pattern *abc_*
if "abc" is already in the Map
get the value of this key in a temp list and append this string at the end of the list
else
add a new entry into the Map
//follow the same for the other patterns.
for each entry in the Map
traverse the list of values
check if this value is present in the set C
if you reach the end of the list,
remove the entry from the Map
That way, you are left with only the keys in the Map, that you need to return.

Put keys in hashmap and retrieve in same order

Below is a piece of code which I use for inserting the values in a hashmap.
String[] folders={"Movies/HD/By Genre/Action","Movies/HD/By Genre/Comedy"};
HashMap<String, String> sdsResults = new HashMap<String, String>();
for(int i=0; i<folders.length; i++){
sdsResults.put(folders[i], null);
}
Iterator<String> itr = sdsResults.keySet().iterator();
while(itr.hasNext()){
System.out.println("keys in map are = "+itr.next());
}
The output is -
keys in map are = Movies/HD/By Genre/Comedy
keys in map are = Movies/HD/By Genre/Action
Now I wanted to keys to come in the same order as how I had put in. i.e. first the Action one should come and then the Comedy. But reverse order is coming.
Can someone explain why is it so? And I want the order to be the same as the folder contents. How can I achieve this?
The order of keys in a hash is not defined. You want a map. Here's a comparison of the internals.
Basically, when you put something in a hash, you scramble the key. This is a one-way function. The whole point is that you can't un-do it -- it's a way of putting 100 things in 10 boxes.
LinkedHashMap should solve the problem of ordering.
Similar question and the answer here Order of values retrieved from a HashMap
You can use ListOrderedMap from Apache's Commons-Collection library to keep the order.

Categories

Resources