how to solve this hashmap logical error in android? - java

I'm facing some known solvable problem but struck out here. In my code, the values are getting stored in ArrayList on the first for loop execution. However, on the 2nd loop and further, the values are overwritten by the final values in the ArrayList. Finally, the lastly entered values are alone getting stored with the number of times of size of the list.
lstall = (ListView)findViewById(R.id.lvall);
sampleArrayList = new ArrayList<HashMap<String, String>>();
ListAdapter sampleListAdapter;
dh = new DBHelper(this);
HashMap<String, String> sampleObjectMap;
List<String> lvall = dh.selectAll();
sampleObjectMap= new HashMap<String, String>();
for(int i=0;i<lvall.size();i++)
{
for (#SuppressWarnings("unused") String sampleObj : lvall)
{
sampleObjectMap.put("title", dh.val1(i));
sampleObjectMap.put("person", dh.pers(i));
sampleObjectMap.put("priorty", setpriority(String.valueOf(dh.prioirty(i))));
sampleObjectMap.put("dat", getDate(Long.valueOf(dh.time(i)),"dd/MM/yyyy"));
}
sampleArrayList.add(sampleObjectMap);
}
I need to store all the values in a arraylist and display within a list view. Any help is highly appreciated and thanks in advance.

You're creating a single HashMap<String, String> and repeatedly overwriting the entries within it.
In fact, you're doing that twice as you have a nested for loop for no obvious reason. I believe you want:
for (int i = 0; i < lvall.size(); i++)
{
HashMap<String, String> sampleObjectMap = new HashMap<String, String>();
sampleObjectMap.put("title", dh.val1(i));
sampleObjectMap.put("person", dh.pers(i));
sampleObjectMap.put("priorty", setpriority(String.valueOf(dh.prioirty(i))));
sampleObjectMap.put("dat", getDate(Long.valueOf(dh.time(i)),"dd/MM/yyyy"));
sampleArrayList.add(sampleObjectMap);
}
It also seems odd to use a list's size but not actually use the values within the list... you might want to consider restructuring your code...

Try it out:
for(int i=0;i<lvall.size();i++)
{
sampleObjectMap= new HashMap<String, String>();
sampleObjectMap.put("title", dh.val1(i));
sampleObjectMap.put("person", dh.pers(i));
sampleObjectMap.put("priorty", setpriority(String.valueOf(dh.prioirty(i))));
sampleObjectMap.put("dat", getDate(Long.valueOf(dh.time(i)),"dd/MM/yyyy"));
sampleArrayList.add(sampleObjectMap);
}

All the elements in the list have the reference of the same Map instance and you are overriding the same Map entries for each iteration.
for(int i=0;i<lvall.size();i++) {
// move it inside the loop
sampleObjectMap= new HashMap<String, String>();
But i don't think that you need a Map here. Just create a class with all the required fields as member variables.

I have not tested it, but try to create new Map
sampleObjectMap = new HashMap<String, String>();
in your inner loop, before you do put. Test it. Later try to use 1 map object and calling clear() after the map is recorded in the sampleArrayList.

Related

Deleting a variable after adding it to a collection

In the following snippet, I want list to be a collection of maps. Instead of creating a new HashMap every time, I tried to clear and reuse the previous variable.
List<Map> list = new ArrayList<>();
Map<String,String> aMap = new HashMap<>();
aMap.put("fou","bar");
list.add(aMap);
aMap.clear();
aMap.put("big", "bang");
list.add(aMap);
System.out.println(list.toString());
I was surprised the value inside the list is affected by the "clear" operation on the variable aMap, the output is as following:
[{big=bang}, {big=bang}]
What's going on here ?
It's a tricky question :) Basically the list holds a reference to the object and not a copy of the object. So when you add aMap to the list you add a reference to that Map variable. Then you modify it (and by doing that you modify that reference that you hold in the list) and then you add the same variable to the list again. So now you have two references (or pointers if you prefer) of the same object. That's why you get such result.
Since you have already added aMap in the beginning to the list,aMap goes on getting added to the list instead rewrite the code as below:
List<Map> list = new ArrayList<>();
Map<String,String> aMap = new HashMap<>();
aMap.put("fou","bar");
list.add(aMap);
aMap.clear();
aMap.put("big", "bang");
// list.add(aMap);> --commented since u have already started adding map values to the array list.
System.out.println(list.toString());

Hashmap arraylist (java)

Okay, so I'm fairly new to programming so apologies if this problem is really simple, I've created an ArrayList inside my Hash Map so that I can add more than one value into my hash map.
My code looks fine (to me) but theres an error on this line "mymap.add(module, new ArrayList>());" saying ( or [ expected.
Wasted way too much time trying to figure this out so thought I'd post here. Thanks in advance for any help. Also: yes I need to do it this way and no I can't use guava MultiMap.
public class hashArray {
HashMap<String, ArrayList<Integer>> mymap = new HashMap<String, ArrayList<Integer>>();
public hashArray() {}
public void addEntryHR( String module, Integer result ) {
mymap.add(module, new ArrayList<Integer>>());
There is a typo and a bug in your line:
// The typo is right here v
mymap.add(mod, new ArrayList<Integer>>());
Remove one of the > and change add to put:
mymap.put(mod, new ArrayList<Integer>());
The error you get, is about the typo. Fixing that typo will give you an error about add to be an unknown method.
You need to first get the list out from map object like below-
ArrayList<Integer> list = mymap.get(mod);
if (list==null){
//then create new ArrayList object and assign to list
list=new ArrayList<Integer>();
}
list.add(number); //adding new number to the list
mymap.put(mod,list); //storing in map
The problems
You create a new ArrayList in new ArrayList<Integer>>() (with contains a syntax error as well - a > too many), but never add number to it.
You are calling add on a HashMap, which doesn't have this method. For maps, it is called put.
Proposed solution
Please see the code below
Map<String, List<Integer>> myMap = new HashMap<>();
public void addEntryHR(String mod, Integer number) {
List<Integer> numbers = new ArrayList<>();
numbers.add(number);
myMap.put(mod, numbers);
}
Other remarks
Use interfaces
It is advised to use the interfaces of the collections rather than the implementations. This means Map<String, String> myMap instead of HashMap<String, String> myMap and List<Integer> instead of ArrayList<Integer>.
Why do this? Because this allows you to be flexible in the collections you use and reduce maintenance effort. Say you change your mind and want to use LinkedList instead of ArrayList, then you just have to change one new ArrayList<>() to new LinkedList<>() instead of all the ArrayList variables used throughout the code.

Merging n number of list into a Map based on a value in List

I have the following objects in an ArrayList and a value in this object is illustrated as the numbers at the beginning, which are Id of something.
I need to create a Map object, whose key should be the id of objects and whose values should be the objects with id. At the end of the day, I would like to have a Map something like that.
I have already solved this problem with two for loops and lots of if statements but it seems very ugly to me.
Any cleaner solution would be appreciated.
Map<Integer, List<Foo>> result = list.stream().collect(Collectors.groupingBy(Foo::getId));
Edited to fit the question edit, it is as simple as this:
ArrayList<Element> list = ...;
HashMap<Integer, List<Element>> map = new HashMap<Integer, List<Element>>();
for(Element e : list) {
ArrayList<Element> auxList;
if(map.contains(e.getId()) {
auxList = map.get(e.getId());
} else {
auxList = new ArrayList<Element>();
map.put(e.getId(), auxList);
}
auxList.add(e);
}
Just iterate over the starting list and add the elements to the map. If the map already contains the id, add it to the list. If not, create a new list.

Looking for a workaround for dynamic variable declaration in a for loop

I have a number of repetitions of a task I would like to put in a for loop. I have to store a time series object as an IExchangeItem, a special class in openDA (a data assimilation software).
This is one of the tasks (that works):
HashMap<String, TimeSeries> items = new LinkedHashMap<String, TimeSeries>();
...
TimeSeries tsc1Q = new TimeSeries(time,value);
id = "Q1";
tsc1Q.setId(id);
this.items.put(id,tsc1Q);
IExchangeItem c1Q = new TimeSeries(tsc1Q);
What changes across the tasks is the id of the time series object and the name of IExchangeItem. I have to create a new IExchangeItem object for each time series.
This is what I tried in the for loop:
HashMap<String, TimeSeries> items = new LinkedHashMap<String, TimeSeries>();
...
TimeSeries temp;
for (int i = 0; i<readDataDim[0]; i++) {
value[0] = values[i];
id = exchangeItemIDs[i];
temp = new TimeSeries(time,value);
temp.setId(id);
this.items.put(id,temp);
IExchangeItem <??> = new TimeSeries(temp); //* How can I handle this line?
}
I know I cannot use dynamic variable names in java and that arrays, lists, or maps are commonly used to work around this issue (this is why I used <??> in the code snippet above. However, I'm a relative beginner with java and I have no clue how I can work around this specific problem since I have to have a new invocation of IExchangeItem for each time series.
From here I take it that my IExchangeItem created in the for loop will not be accessible outside the for loop so how can I initialise n replicates of IExchangeItem outside the for loop?
Edit:
Does a HashMap create n instances of IExchangeItem if I try something like this?
HashMap<String,IExchangeItem> list = new LinkedHashMap<String,IExchangeItem>();
Just one suggestion, try to write a separate method when you can pass the size of the array or a fixed number (based on array), then you created a hashMap and add that many number of instances with its keys, and values, cannot post this as a comment and hence posting it as an answer.
Try to create a new method using the value of readDataDim[0] value,
public Map<String, IExchangeItem> createAndInitialzeMap(int maxValue) {
Map<String, IExchangeItem> map = new HashMap<>();
String temp = "tempName";
for(int i =0; i < maxValue ; i ++ ) {
map.put(temp+i, new IExchangeItem());
}
return map;
}
return this way you can initialize your map along with its variable name and you can use it in your app anywhere. However I would consider refactoring if such code exists and time permits.
One more thing you should read about hashMap. :) :)

Java, How to add values to Array List used as value in HashMap

What I have is a HashMap<String, ArrayList<String>> called examList. What I want to use it for is to save grades of each course a person is attending. So key for this HashMap is couresID, and value is a ArrayList of all grades (exam attempts) this person has made.
The problem is I know how to work with array lists and hashmaps normally, but I'm not sure how to even begin with this example. So how would I, or example, add something to ArrayList inside HashMap?
You could either use the Google Guava library, which has implementations for Multi-Value-Maps (Apache Commons Collections has also implementations, but without generics).
However, if you don't want to use an external lib, then you would do something like this:
if (map.get(id) == null) { //gets the value for an id)
map.put(id, new ArrayList<String>()); //no ArrayList assigned, create new ArrayList
map.get(id).add(value); //adds value to list.
String courseID = "Comp-101";
List<String> scores = new ArrayList<String> ();
scores.add("100");
scores.add("90");
scores.add("80");
scores.add("97");
Map<String, ArrayList<String>> myMap = new HashMap<String, ArrayList<String>>();
myMap.put(courseID, scores);
Hope this helps!
First create HashMap.
HashMap> mapList = new HashMap>();
Get value from HashMap against your input key.
ArrayList arrayList = mapList.get(key);
Add value to arraylist.
arrayList.add(addvalue);
Then again put arraylist against that key value.
mapList.put(key,arrayList);
It will work.....
First you retreieve the value (given a key) and then you add a new element to it
ArrayList<String> grades = examList.get(courseId);
grades.add(aGrade);
Java 8+ has Map.compute for such cases:
examList.compute(courseId, (id, grades) ->
grades != null ? grades : new ArrayList<>())
.add(value);
First, you have to lookup the correct ArrayList in the HashMap:
ArrayList<String> myAList = theHashMap.get(courseID)
Then, add the new grade to the ArrayList:
myAList.add(newGrade)
Can also do this in Kotlin without using any external libraries.
var hashMap : HashMap<String, MutableList<String>> = HashMap()
if(hashMap.get(id) == null){
hashMap.put(id, mutableListOf<String>("yourString"))
} else{
hashMap.get(id)?.add("yourString")
}
HashMap<String, ArrayList<ObjectX>> objList = new HashMap<>();
if(objList.containsKey(key))
objList.get(key).add(Object1);
else
objList.put(key, new ArrayList<ObjectX>(Arrays.asList(Object1)));

Categories