Kopi Bryant
Kopi Bryant

Reputation: 1364

Android: Iterate through Object ArrayList throwing ConcurrentModificationException

I am doing the Android scanning barcode application and I have an object ArrayList ArrayList<Item> itemArrayList for storing all the data. However, I want to check every received for item barcode is unique so I check the ArrayList if it is having the rackname and itemname from the saveItem method.

Below is saveItem method:

private void saveItem(final String rackName, final String itemName, String date, String time) {
    Item saveItem = new Item(username, rackName, itemName, date, time);
    if (itemArrayList.size() != 0) {
        synchronized (itemArrayList) {
            for (Iterator<Item> iterator = itemArrayList.iterator(); iterator.hasNext(); ) {
                Item item = iterator.next();
                if (rackName.equals(item.getRackNumber()) && itemName.equals(item.getItemNumber())) {
                    dialogDuplicate(itemName); //dialog for duplicate item
                } else {
                    itemArrayList.add(saveItem);
                    itemAdapter.notifyDataSetChanged();
                }
            }
        }
    } else {
        Toast.makeText(getApplicationContext(), "Saved for the 1st item", Toast.LENGTH_SHORT).show();
        itemArrayList.add(saveItem);
        itemAdapter.notifyDataSetChanged();
    }
}

But this method throw java.util.ConcurrentModificationException which occurred from Item item = iterator.next() which I dont know why it would occur. What did I do wrong?

Upvotes: 0

Views: 35

Answers (2)

firemaples
firemaples

Reputation: 1541

It would be more efficient if you break the for-loop while it is a duplicate. It's no need to check all items in the list.

 private void saveItem(final String rackName, final String itemName, String date, String time) {
    Item saveItem = new Item(username, rackName, itemName, date, time);
    if (itemArrayList.size() != 0) {
        boolean duplicate = false;
        
        for (Item item : itemArrayList) {
            if (rackName.equals(item.getRackNumber()) && itemName.equals(item.getItemNumber())) {
                duplicate = true;
                //if it is duplicate, break the for-loop immediately
                break;
            }
        }
        
        //check if duplicate is true
        if (duplicate) {
            dialogDuplicate(itemName);
        } else {
            itemArrayList.add(saveItem);
            itemAdapter.notifyDataSetChanged();
        }
    } else {
        Toast.makeText(getApplicationContext(), "Saved for the 1st item", Toast.LENGTH_SHORT).show();
        itemArrayList.add(saveItem);
        itemAdapter.notifyDataSetChanged();
    }
}

Upvotes: 1

Kopi Bryant
Kopi Bryant

Reputation: 1364

Thanks for @Yu-Long Chen for point me out.

The problems come from the itemArrayList.add(saveItem); while the ArrayList will continue to add the new Item if there is no duplicated and this trigger the concurrency exception.

So I made a flag and an ArrayList<Boolean> booleanList for checking duplicated. booleanList store every boolean and check if the list contains true after the iterator finished. If found true, then it must be duplicated. Otherwise, it is a new item.

private void saveItem(final String rackName, final String itemName, String date, String time) {
    Item saveItem = new Item(username, rackName, itemName, date, time);
    ArrayList<Boolean> boleanList = new ArrayList<>();
    if (itemArrayList.size() != 0) {
        for (Iterator<Item> iterator = itemArrayList.iterator(); iterator.hasNext(); ) {
            Item item = iterator.next();
            if (rackName.equals(item.getRackNumber()) && itemName.equals(item.getItemNumber())) {
                duplicate = true;
                boleanList.add(duplicate);
            } else {
                duplicate = false;
                boleanList.add(duplicate);
            }
        }
        //check if duplicate is true
        if(boleanList.contains(true)){
            dialogDuplicate(itemName);
        }else{
            itemArrayList.add(saveItem);
            itemAdapter.notifyDataSetChanged();
        }
    } else {
        Toast.makeText(getApplicationContext(), "Saved for the 1st item", Toast.LENGTH_SHORT).show();
        itemArrayList.add(saveItem);
        itemAdapter.notifyDataSetChanged();
    }
}

Upvotes: 0

Related Questions