I am working on an android project and I am facing a problem and the problem is:
Arraylist empty when I return it.
Here is my java code:
ArrayList<ArrayList<Object>> container = new ArrayList<ArrayList<Object>>();
ArrayList<Object> itemRow = new ArrayList<Object>();
JSONObject jsonObj = new JSONObject(result);
JSONArray allElements = jsonObj.getJSONArray("Table");
Log.i("allElements", "" + allElements);
for (int i = 0; i < allElements.length(); i++) {
itemRow.add(allElements.getJSONObject(i).getString("ParentName").toString());
itemRow.add(allElements.getJSONObject(i).getString("ParentEmailID").toString());
itemRow.add(allElements.getJSONObject(i).getString("ParentContact").toString());
itemRow.add(allElements.getJSONObject(i).getString("ParentAddress").toString());
itemRow.add(allElements.getJSONObject(i).getString("ParentProfilePictureName").toString());
itemRow.add(allElements.getJSONObject(i).getString("StudentName").toString());
Log.i("itemRow", "itemRow at index: " + i + ", " + itemRow);
container.add(((i*2)/2), itemRow);
itemRow.clear();
}
return container;
In this code I have two Arraylist one for contain all the elements and another one for storing single row of elements. These Arraylist are loaded from JSONArray, all is working fine and I can print data from item row (Arraylist which take single row) and store into main Arraylist (container).
But when I return this Arraylist (container) and print in logcat it shows empty Arraylist like
[[], [], [], [], []].
I cannot understand why this happen please help me to solve this issue.
Thanks.
Because you did, It still refers to the object that is added to container
itemRow.clear();
You might like to reinitialize it
itemRow = new ArrayList<Object>();
Stop clearing the list, and it won't be empty anymore:
itemRow.clear();
You should create a new list at each iteration. Put the following line of code inside the for loop:
ArrayList<Object> itemRow = new ArrayList<Object>();
Remember that Java passes references to objects. So the container list holds a reference to the list you add to it. It doesn't make a copy of the list. So your current code adds several references to the same list object to the container list, and you clear the list each time you add it. It thus contains N references to the same empty list at the end of the loop.
Your assessment is misleading/incorrect, the ArrayList is not empty, and actually contains five elements.
Each element of the array list is an empty list. This is because of the last two lines within your loop:
container.add(((i*2)/2), itemRow);
itemRow.clear();
The first line adds the itemRow to the container, as you expect. The next line calls clear() on the row you've just added - so everything in the container will always be empty by the time your method exits.
It looks like this issue was caused by you trying to reuse the same itemRow object throughout the method, which isn't going to work. To fix your problem, move the
ArrayList<Object> itemRow = new ArrayList<Object>();
constructor inside the loop (as the first line), and then stop calling clear() on it at the end. Now each JSON element will have a separate row list created for it, and once you've added these to the container they will maintain their contents.
Your assumption that container actually copies every arraylist in itself is not right. it refers to those already created rather having copies of each List.
try this
container.add(((i*2)/2), itemRow.clone());
as it about JAVA referencing...
Related
What the difference between assigning an arraylist to another and using method addAll between two arraylists?
1 > arrayList = arrayList; //should assign value of later arrayList to the first.
2> arrayList.addAll(arrayList) //add all the data of the later list to first.
the first completely replaces the data in the list ?
the second one for appending data in the list(if it already has any) ???
if i do arrayList.add(arrayList) without assigning any data to the first list, will it insert any data ?
I did the following code for testing and found results that i do'not really know.
secondList.add("1");
secondList.add("2");
firstList = secondList;
Log.i("CHECK","first list = "+ firstList);
firstList.addAll(secondList);
Log.i("CHECK","Firs list add : "+firstList);
firstList.clear();
firstList.addAll(secondList);
Log.i("CHECK","Firs list add 2 : "+firstList);
Result were :
CHECK: first list = [1, 2]
CHECK: Firs list add : [1, 2, 1, 2]
CHECK: Firs list add 2 : []
i was expecting the last log to have result like : [1,2]
as mentioned in docs.oracle.com
addAll- Appends all of the elements in the specified collection to the
end of this list, in the order that they are returned by the specified
collection's Iterator.
and if there's no data in the list ? then what will addAll DO ?
When you do:
firstList = secondList;
What you are saying is actually "to make firstList and secondList refer to the same list". After the line is executed, there will only be one list and two variables both refer to that list.
This is why after you cleared firstList, secondList lost all the elements as well. They refer to the same thing. This has nothing to do with addAll. When you called firstList.addAll(secondList), you are basically adding appending an empty list to another empty list, which results in an empty list.
when you use arrayList = arrayList2; then you are assigning the reference of arrayList2 in first list. That means they are referring to the same list.
and when you use arrayList.addAll(arrayList2) then they are two different list reference.
Now come back to your code (lets denote firstlist as f, second as s)
secondList.add("1"); // f={}, s = {1}
secondList.add("2"); // f={}, s = {1,2}
firstList = secondList; // f= s = {1, 2}
Log.i("CHECK","first list = "+ firstList); // so printing 1,2
firstList.addAll(secondList);// it is actually adding itself.. so f= s = {1,2,1,2}
Log.i("CHECK","Firs list add : "+firstList);
firstList.clear(); // clear boths as s = f
firstList.addAll(secondList); // as boths are blank so overall blank
Log.i("CHECK","Firs list add 2 : "+firstList);
I learned about this in class, Java doesnt really specify when it passes by value or passes by reference, but for the sake of arrayList's, they are pass by reference unless you specifically create new elements. When you say
firstArray = secondArray;
firstArray gets the memory address of the second array, therefore when you cleared the first array, you actually cleared the memory which the second array also shares.
Good luck!
I am passing Arraylist of ParseObject, and then i am putting one one foreach loop to extract the items with a condition when user object is not equals to null. There are two problems which i am facing.
1. If i am doing the following lines of code by passing different data to another list and then pass that list in my adapter, i am getting random data with numbers for example: If on item # 1 the name is "MAC" then it is showing in item 3.
ArrayList<ParseObject> checkRequestedNetArrayList = new ArrayList<ParseObject>();
requestedNetArrayList = (ArrayList<ParseObject>) objects;
MyResponsibilitesActivity.requestedNetArrayList = requestedNetArrayList;
adapterRequest = new GenericAdapter<ParseObject>(
getApplicationContext(),
requestedNetArrayList,
R.layout.requested_trust_net_list_item,
requestedDataBinder);
requestListView.setAdapter(adapterRequest);
requestedNetArrayList = (ArrayList<ParseObject>) objects;
for(ParseObject object: objects){
System.out.println(object);
object.getParseObject("user");
if(object.has("user")){
checkRequestedNetArrayList.add(object);
}else{
checkRequestedNetArrayList.remove(object);
}
}
adapterRequest = new GenericAdapter<ParseObject>(
getApplicationContext(),
checkRequestedNetArrayList,
R.layout.requested_trust_net_list_item,
requestedDataBinder);
requestListView.setAdapter(adapterRequest);
If i am doing the following line of code to just direct giving the items in the same list, i am getting the java.util.ConcurrentModificationException
for(ParseObject object: objects){
if(object.has("user")){
requestedNetArrayList.add(object);
}
}
else{
requestedNetArrayList.remove(object);
}
adapterRequest = new GenericAdapter<ParseObject>(
getApplicationContext(),
requestedNetArrayList,
R.layout.requested_trust_net_list_item,
requestedDataBinder);
requestListView.setAdapter(adapterRequest);
}
Please help me out here.
You can not remove an element from list while accessing it.
You have to use Iterator.
Where ever you are removing the object, use it.remove();
Iterator<ParseObject> it = objects.iterator();
while(it.hasNext()){
Object object = it.next();
//your stuff
it.remove();
}
I think you might want to check this article about deep copy also.
UPDATE
Since you want to add elements to the list it is not directly possible with iterator. Now you are facing problem because you are directly assigning objects to requestedNetArrayList instead of that do it in the following way :
ArrayList<ParseObject> requestedNetArrayList = new ArrayList<>(objects);
Then iterate over objects as you are doing now, and remove from or add to
requestedNetArrayList (which you are pretty much already doing).
When you make iteration using for-each construction for Collection
for (Object x : collection) ...
you have implicit creation of Iterator object for that Collection. This iterator performs a check: is collection was changed since iterator was created? If so, throwing an exception. So, you should avoid to any modify to your collection, until iterator done. That means, you should not use add and remove.
In either way, it is better to access ArrayList by index, because it will prevent creation of Iterator object. Like this:
for (int i = objects.size() - 1; i >= 0; i--) {
ParseObject object = objects.get(i);
// when iterating from tail to head, you can safely add or remove objects to/from this array list
}
Instead of assigning the reference of objects to requestedNetArrayList,
create a new ArrayList with the same contents
requestedNetArrayList=new ArrayList<ParseObject>(objects);
Then you can iterate on objects and modify requestedNetArrayList.
(Right click and open image in new tab to see it bigger)
nothing much to say but the code:
System.out.println("map add:" + parts[i].split("=")[0] + "=" + list);
map2.put(parts[i].split("=")[0], list);
prints out the exact same thing as what is added to the map but what is printed and what is on the map are completely different?
why is this?
You're adding the same list at each iteration, and hence the keys are referencing the same list (see figure below).
What you're actually doing is this :
You create a list containing the values [root, like] and you associate this list with the key root
In the second iteration, you clear the list and you add [eat, it] to this list and associate it with another key xsubj.
Since you did'nt create a new object, the keys root and xsubj point to the same list object and hence each change on the list will be reflected for all the keys that share it.
So that's why at the end you got this output.
Instead of calling clear(), create a new list at each iteration.
for(int i = 0; i < parts.length; i++){
list = new ArrayList<>();
list.add(...);
/**
* The code
**/
}
this is my first question on Stack! I'm having a small problem populating a 2d arraylist with arraylists, using the add method. After adding my first arraylist to the 2d arraylist, and attempting to repopulate the SAME 1d arraylist, adding this 1d arraylist again to the 2d arraylist seems to alter the first element of the 2d arraylist I added...
ArrayList<ArrayList<String>> twoDArray = new ArrayList<ArrayList<String>>();
ArrayList<String> oneDArray = new ArrayList<String>();
oneDArray.add("a");
twoDArray.add(oneDArray);
System.out.println("First element in twoDArray: " + twoDArray.get(0)); //prints [a]
twoDArray.add(oneDArray);
oneDArray.clear();
oneDArray.add("b");
twoDArray.add(oneDArray);
System.out.println("First element in twoDArray:" + twoDArray.get(0)); //prints [b]
In practice, oneDArray is actually a local variable inside an iterator, hence why I am attempting to re-use it. I add elements to oneDArray, and when a check returns true, I add oneDArray to twoDArray, empty oneDArray, then continue this process, creating a list of lists.
Would this be to do with twoDArray.get(0) actually holding a pointer to oneDArray, and not it's actual value? If so, how might I work around this issue?
Any help would be much appreciated :)
EDIT: solution to above issue
ArrayList<ArrayList<String>> twoDArray = new ArrayList<ArrayList<String>>();
ArrayList<String> oneDArray = new ArrayList<String>();
oneDArray.add("a");
twoDArray.add(new ArrayList<String>()); // Create new arraylist inside twoDArray
twoDArray.get(0).add(oneDArray.get(0)); // Populate new arraylist rather than hold reference to oneDArray
oneDArray.clear();
oneDArray.add("b");
twoDArray.add(new ArrayList<String>());
twoDArray.get(1).add(oneDArray.get(0));
Yes if you are not creating oneDArray inside the loop and merely clearing it will be overwritting on each iteration, that is why the elements are lost. This is indeed because you have the same reference to the same inner arraylist. You should do ArrayList<String> innerToBeAdded = new ArrayList<>() inside your loop conditional to create a new arraylist.
You say " I add oneDArray to twoDArray, empty oneDArray, then continue this process, creating a list of lists", but what you are really doing is adding the same array multiple times to the twoDArray. Because the exact same array is added multiple times to the twoDArray, when you clear() it, it clears all the values, and when you add a value to oneDArray it will appear in all the places in twoDArray.
Instead of clearing the array, what you should do is create a new instance array: oneDArray = new ArrayList<String>(); This will create a different array as each member of twoDArray
Hello I want to Fill Up my Arraylist of Arraylist named as QuestionIdList_Section
and for that i have make the temp Arraylist named QUESTION_ID_Of_SectionId_Temp that will be clear after adding into QuestionIdList_Section
My Code is as Below so that you can understand how i have codded :
public static ArrayList<String> QUESTION_ID_Of_SectionId_Temp = new ArrayList<String>();
public static ArrayList<ArrayList<String>> QuestionIdList_Section = new ArrayList<ArrayList<String>>();
QUESTION_ID_Of_SectionId_Temp.add("Hello");
QUESTION_ID_Of_SectionId_Temp.add("Hiii");
QuestionIdList_Section.add(0,QUESTION_ID_Of_SectionId_Temp);
Log.i(TAG, "******Before " + QuestionIdList_Section);
Log.i(TAG, "******Before "+ QUESTION_ID_Of_SectionId_Temp);
QUESTION_ID_Of_SectionId_Temp.clear();
Log.i(TAG, "******After " + QuestionIdList_Section);
Log.i(TAG, "******After " + QUESTION_ID_Of_SectionId_Temp);
After Executing the Code i am getting Different Result for both Variable.
as Below :
******Before [[Hello, Hiiii]]
******Before [Hello, Hiiii]
******After [[]]
******After []
can some one Please Help me to Understand where i am lacking here. i want to clear temp arraylist so that i can put the different Values for UESTION_ID_Of_SectionId_Temp so for second index of QuestionIdList_Section i will set the Value different.
Thanks in Advance.
QUESTION_ID_Of_SectionId_Temp is just a reference.
So if you clear it, the value in QuestionIdList_Section will also be clear.
What you should do is
QUESTION_ID_Of_SectionId_Temp = new ArrayList<String>();
instead of
QUESTION_ID_Of_SectionId_Temp.clear();
The ArrayList associated with QuestionIdList_Section holds a reference of the ArrayList associated with QUESTION_ID_Of_SectionId_Temp.
Thus, when clearing the temp ArrayList, it will also reflect on the ArrayList which is in QuestionIdList_Section.
You might want to create a new instance of temp array and add it to the main array list as follows:
QUESTION_ID_Of_SectionId_Temp = new ArrayList<String>();
QuestionIdList_Section.add(QUESTION_ID_Of_SectionId_Temp);
After doing so, every element you add to QUESTION_ID_Of_SectionId_Temp will be shown in thew second index of QuestionIdList_Section.
You are clearing the QUESTION_ID_Of_SectionId_Temp array which means it has no elements. The second "After" print displays it empty.
The first "After" displays the contents of the QuestionIdList_Section which still contains the ArrayList above, which is empty now.