ConcurrentModificationException at for each android - java

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.

Related

Clone a list and modify the property of an element to list does not work in Java

I tried to make a clone of an arraylist so there will be two lists created. After that, I tried to modify the property of an element in one of the lists. When I compared the lists, it should have given me false for equal result but instead it is true. I assume this got to do with the pointer of the element or list. Is there any solution to fix that?
My code is like this:
List<UnifiedBucket> ubsCopy = new ArrayList<>(ubs);
ubsCopy.get(14).setRawPolicy(null);
UnifiedBucket ub1 = ubs.get(14);
UnifiedBucket ub2= ubsCopy.get(14);
System.out.println(ub1 == ub2);
System.out.println(ub1.getRawPolicy().equals(ub2.getRawPolicy()));
what you want to have is a deep copy but the constructor does shallow copy , look at public ArrayList(Collection c)
if you want to make a deep copy use Iterator on ArrayList like this :
List<UnifiedBucket> UnifiedBucketClone = new ArrayList<>();
Iterator<UnifiedBucket> iterator = ubs.iterator();
while(iterator.hasNext()){
UnifiedBucketClone .add((UnifiedBucket) iterator.next().clone());
}

Getting the clicked object from an array list

I have an object that is in an arraylist, called a PowerUp. I want these to be clickable, and when they are clicked, they will be removed from the screen, and ultimately taken out of the arraylist. I have inserted the handler into the class HealthPack, which in turn extends PowerUp. I am trying to access the certain HealthPack that was clicked on and remove it from that list. I keep getting either it not working correctly, or a ConcurrentModificationException. Here is my code I am trying to work with:
for (int i = 0; i < ((SurvivalMode) m).getPowerUps().size(); i++) {
PowerUp p = ((SurvivalMode) m).getPowerUps().get(i);
if (p.equals(hp)) { // HealthPack hp = this;
((SurvivalMode) m).getPowerUps().remove(p);
addPoints();
}
}
This current code actually throws a ConcurrentModificationException when I go to click on a HealthPack when the list is both adding it, and another is iterating through it. I have tried synchronizing the methods that mess with the list, but it didn't help.
How would I keep my program from throwing a ConcurrentModificationException if one method is trying to remove an element from the list while another one is either iterating through the list or one is adding or removing an element from the list?
EDIT:
Here is some additional code that actually modifies the arraylist for the items:
if (powerups.size() >= 15 || isPaused()) return;
int gen = random.nextInt(10);
if (gen == 0) {
powerups.add(new HealthPack(this));
addMouseListener(powerups.get(powerups.size() - 1).getMouseListener());
}
}
and some code that actually iterates through that list (which throws the ConcurrentModificationException):
for (PowerUp p : powerups) p.update();
CURRENT METHOD:
Here is the current method that I have attempted to remove from the list on click, but it still doesn't work so well, as in it doesn't remove anything at all or it will remove the wrong one, and sometimes even calls the method for all of the other PowerUps in the list:
Iterator<PowerUp> iter = ((SurvivalMode) m).getPowerUps().iterator();
while (iter.hasNext()) {
PowerUp p = (HealthPack) iter.next();
if (p.equals(hp)) {
((SurvivalMode) m).getPowerUps().remove(p);
}
CellDefender.getSounds().play(SoundType.HEALTH_PACK);
break;
}
Update 2:
What I have recently done is actually copy the array list within another point, and it partially helps to reduce the errors (within my update method):
CopyOnWriteArrayList<PowerUp> cpowerups = new CopyOnWriteArrayList<PowerUp>();
for (int i = 0; i < powerups.size(); i++) {
cpowerups.add(powerups.get(i));
}
for (PowerUp p : cpowerups) p.update();
And I would like to ask one thing, is there a way to detect if a list is currently being modified, and if the list is being modified to break out of the loop?
You have to use Iterator for loop to remove elements from ArrayList.
Iterator<PowerUp> iter = ((SurvivalMode) m).getPowerUps().iterator();
while(iter.hasNext()) {
PowerUp p = iter.next();
// your conditions to remove element here
iter.remove();
}
Since I don't know your entire code, I have to make some assumptions.
My first assumption is, that your problematic code fragment is called somehow by the update method of the PowerUp class.
As stated in [1], a for each loop uses an Iterator object to iterate over the elements of an ArrayList.
Those Iterator objects returned by an ArrayList are fail-fast.
That is, their methods throw a ConcurrentModificationException if the ArrayList is modified in any way after the creation of such an Iterator object, except through the object itself. (cf. [2])
If my assumption is correct, your code for (PowerUp p : powerups) p.update(); creates such an Iterator object and modifies the ArrayList within the other given code fragment.
That is the reason why you encounter the same exception with the code proposed by Alex.
A solution of your problem is the use of a CopyOnWriteArrayList whenever you iterate over a Collection (ArrayList, LinkedList, etc.) It creates a shallow copy of the collection and iterates over the elements of the copy, so that you can modify the original collection without the occurrence of a ConcurrentModificationException.
That means, you have to replace for (PowerUp p : powerups) p.update(); with for (PowerUp p : CopyOnWriteArrayList(powerups) p.update(); and use
Iterator<PowerUp> iter = ((SurvivalMode) m).getPowerUps().iterator();
while(iter.hasNext()) {
PowerUp p = iter.next();
// your conditions to remove element here
iter.remove();
}
as proposed by Alex.

ConcurrentModificationException In a Java BO

I am getting a java.util.ConcurrentModificationException in this code and can't seem to understand why, or fix it.
In the BO I have this (privileges is an arraylist inside the BO)
public void setPrivilegename(String privilegename) {
this.privileges.add(privilegename);
}
List<PrivilegeObjectBO> arraylist = new ArrayList<PrivilegeObjectBO>();if (rs != null) {
while (rs.next()) {
for (BO bo : arraylist) {
if (bo.getRolepkey()==rs.getInt("ROLE_PKEY")) {
bo.setPrivilegename(rs.getString("SP.NAME"));
}else{
BO newobj = new BO();
newobj.setRolepriviledgepkey(rs.getInt("PRIVILEGE_PKEY"));
newobj.setProticolpkey(protocol);
newobj.setPrivilegename(rs.getString("SP.NAME"));
newobj.setRolepkey(rs.getInt("SRP.ROLE_PKEY"));
arraylist.add(newobj);
}
}
}
}
As per ArrayList javadoc
The iterators returned by this class's iterator and listIterator
methods are fail-fast: if the list is structurally modified at any
time after the iterator is created, in any way except through the
iterator's own remove or add methods, the iterator will throw a
ConcurrentModificationException.
for (BO bo : arraylist)
Above for-each loop gets Iterator for the list and
arraylist.add(newobj);
You are trying to modify the list without using iterators own methods, which results in ConcurrentModificationException
Here is SO discussion on possible solutions.
In java, you will always get a ConcurrentModificationException when you modify the Collection while you are iterating over it.
Possible solution: use a temporary Collection for added or deleted items, and add or delete those items after the iteration is done.
You cannot iterate over ArrayList and add elements to it at the same time with foreach.
Use iterator, like this:
Iterator<PrivilegeObjectBO> iterator = arraylist.iterator();
while (iterator.hasNext()) {
...
}
Others have already pointed out that add-ing to an ArrayList while iterating over it is disallowed.
But to solve your problem anyway, it looks like you need to iterate over the entire list before attempting to add to it, because it your loop appears to be checking to see if anything in the list matches your row to avoid duplicates. In this case you don't want to add to the list while iterating over it because you don't know whether the list has a duplicate until the end.
So just iterate through and check to see if a match is found:
List<PrivilegeObjectBO> arraylist = new ArrayList<PrivilegeObjectBO>();
if (rs != null) {
while (rs.next()) {
boolean found = false;
for (BO bo : arraylist) {
if (bo.getRolepkey() == rs.getInt("ROLE_PKEY")) {
bo.setPrivilegename(rs.getString("SP.NAME"));
found = true;
}
}
if (!found) {
BO newobj = new BO();
newobj.setRolepriviledgepkey(rs.getInt("PRIVILEGE_PKEY"));
newobj.setProticolpkey(protocol);
newobj.setPrivilegename(rs.getString("SP.NAME"));
newobj.setRolepkey(rs.getInt("SRP.ROLE_PKEY"));
arraylist.add(newobj);
}
}
}
Unless you really do want to add a new BO for every non-matching BO already in the list...
Maybe you can take a look at Collections.synchronizedList(List<?>) static method.
It should return a thread safe List from the List object given, and you should not get the exception anymore.
Otherwise, you could try (if applicable) to set the method that accesses to the list synchronized, by adding the keyword synchronized in the method declaration.

Arraylist empty when return

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...

Getting a ConcurrentModificationException thrown when removing an element from a java.util.List during list iteration? [duplicate]

This question already has answers here:
Iterating through a Collection, avoiding ConcurrentModificationException when removing objects in a loop
(31 answers)
Closed 5 years ago.
#Test
public void testListCur(){
List<String> li=new ArrayList<String>();
for(int i=0;i<10;i++){
li.add("str"+i);
}
for(String st:li){
if(st.equalsIgnoreCase("str3"))
li.remove("str3");
}
System.out.println(li);
}
When I run this code,I will throw a ConcurrentModificationException.
It looks as though when I remove the specified element from the list, the list does not know its size have been changed.
I'm wondering if this is a common problem with collections and removing elements?
I believe this is the purpose behind the Iterator.remove() method, to be able to remove an element from the collection while iterating.
For example:
Iterator<String> iter = li.iterator();
while(iter.hasNext()){
if(iter.next().equalsIgnoreCase("str3"))
iter.remove();
}
The Java 8 way to remove it from the List without Iterator is:
li.removeIf(<predicate>)
i.e.
List<String> li = new ArrayList<String>();
// ...
li.removeIf(st -> !st.equalsIgnoreCase("str3"));
Note that this exception does not always indicate that an object has been concurrently modified by a different thread. If a single thread issues a sequence of method invocations that violates the contract of an object, the object may throw this exception. For example, if a thread modifies a collection directly while it is iterating over the collection with a fail-fast iterator, the iterator will thow this exception
Taken from http://download.oracle.com/javase/1.4.2/docs/api/java/util/ConcurrentModificationException.html
yes people run into it -- the problem is you can't modify the list while iterating over it. I have used 2 alternatives in the past:
You can keep track of the indexes of the items you want to remove, and then remove them after you are done iterating.
Or you can copy all the ones you want to keep into a new list as you iterate, and then discard the old list when done.
those options assume you have to iterate over the list to find the elements to remove -- useful in cases where the list elements are complex objects with properties you might test on.
In your particular case, you dont even need to iterate, as you can just use removeAll. Look at the API here. There are also nifty methods like retainAll that discard everything that is not in the argument. You can use remove/retain-like methods whenever the objects in the list implement equals and hashcode properly. If you cannot rely on equals/hashcode to identify equality between instances in your app, you will have to do the removal yourself....
Try this (Java 8):
list.removeIf(condition);
You could make a copy of list you want to remove element from, directly in for-each loop. For me, that is the simpliest way. Something like this:
for (String stringIter : new ArrayList<String>(myList)) {
myList.remove(itemToRemove);
}
Hope that will help you..
I think it is worth mentioning the Java 8 version
#Test
public void testListCur() {
List<String> li = new ArrayList<String>();
for (int i = 0; i < 10; i++) {
li.add("str" + i);
}
li = li.stream().filter(st -> !st.equalsIgnoreCase("str3")).collect(Collectors.toList());
System.out.println(li);
}
ArrayList has field modCount - count of collection modifications
When you invoke method iterator() creates new object Itr. It has field expectedModCount. expectedModCount field initialize by modCount value. When you invoke
li.remove("str3");
modCount increments. When do you try access to li via iterator
checks that expectedModCount == modCount
and if it is false throws ConcurrentModificationException
Hence if you get iterator and after collection modified - iterator is considered not valid and you cannot use it.
I think that best answer is from bigdev.de, but i would like to add something to it(like if the item is removed from a list, maybe you would like to log that somewhere or something):
List<String> list = new ArrayList<>();
list.removeIf(a -> {
boolean condition = a.equalsIgnoreCase("some condition");
if(condition)
logger.info("Item removed from the list: " + a);
return condition;
});
I got this problem and I think the easier way is the same with the second way that hvgotcodes gave.
Or you can copy all the ones you want to keep into a new list as you iterate, and then discard the old list when done.
#Test
public void testListCur(){
List<String> li=new ArrayList<String>();
for(int i=0;i<10;i++){
li.add("str"+i);
}
List<String> finalLi = new ArrayList<String>();
for(String st:li){
if(st.equalsIgnoreCase("str3")){
// Do nothing
} else {
finalLi.add(st);
}
}
System.out.println(finalLi);
}
I looped a different way...
public void testListCur(){
List<String> li=new ArrayList<String>();
for(int i=0;i<10;i++){
li.add("str"+i);
}
for(int i=0; i<li.size(); i++)
if(li.get(i).equalsIgnoreCase("str3"))
li.remove(i--);
System.out.println(li);
}

Categories

Resources