Reputation: 41
I have below java piece of code that throws ConcurrentModificationException
below is the java piece of code
below is the lists that are being declared
List<BrokerInvoiceLineItem> brokerInvoiceLineItems= new ArrayList<BrokerInvoiceLineItem>();
brokerInvoiceLineItems=brokerInvoice.getLineItems();
below is the the piece of code that is throwing concurrentmodification exception
if (brokerInvoiceLineItems == null) {
brokerInvoiceLineItems = brokerInvoiceHome.findLineitemsByInvoiceId(brokerInvoice.getId());
}
for (BrokerInvoiceLineItem brokerInvoiceLineItem : brokerInvoiceLineItems) {
if (fetchNewAndOldCFandAmend(brokerInvoiceLineItem)) {
if (!isAnyValid)
isAnyValid = true;
}
}
now the issue is that if brokerInvoiceLineItems is not null then for the first iteration it goes inside the loop and the value is set true of variable named isAnyValid but as soon the first iteration is over then for the second iteration it goesagain to the line for (BrokerInvoiceLineItem brokerInvoiceLineItem : brokerInvoiceLineItems){
and then it does not go the next line it throws concurrent modification exeption
so this means it must be modifying brokerInvoiceLineItems size while iterating through it. This is probably occurring in fetchNewAndOldCFandAmend
so i am consider making a copy of brokerInvoiceLineItems and modifying the copy instead. so please advise how can i pass the copy to fetchNewAndOldCFandAmend(brokerInvoiceLineItem)
Also please advise how to use copyonwriteArray list also to avoid such error
Upvotes: 2
Views: 3342
Reputation: 1
You should create a new ArrayList and add to it all the elements of your previous ArrayList object.
ArrayList<BrokerInvoiceLineItem> otherList = new ArrayList<BrokerInvoiceLineItem>();
otherList.addAll(brokerInvoiceLineItems);
Note: if you change your for statement for another like:
for(int i=0;i<brokerInvoiceLineItems.size();i++){
You'll not get that ConcurrentModificationException.
Update: example code:
if (brokerInvoiceLineItems == null) {
brokerInvoiceLineItems = brokerInvoiceHome.findLineitemsByInvoiceId(brokerInvoice.getId());
}
ArrayList<BrokerInvoiceLineItem> otherList = new ArrayList<BrokerInvoiceLineItem>();
otherList.addAll(brokerInvoiceLineItems);
for (BrokerInvoiceLineItem brokerInvoiceLineItem : brokerInvoiceLineItems) {
if (fetchNewAndOldCFandAmend(otherList)) {
if (!isAnyValid)
isAnyValid = true;
}
}
Upvotes: 0
Reputation: 2371
I'm assumming that you are modifying the brokerInvoiceLineItems
in the method fetchNewAndOldCFandAmend
. You can use a CopyOnWriteArrayList
instead of the ArrayList. This allows you to iterate the list and at the same time update it. There is some cost to this since it creates a new array everytime you add something to it. A sample code would look like this:
// Member field declaration
List<BrokerInvoiceLineItem> brokerInvoiceLineItems;
// Retrieve the list of objects
List<BrokerInvoiceLineItem> items = brokerInvoice.getLineItems();
if (items == null) {
items = brokerInvoiceHome.findLineitemsByInvoiceId(brokerInvoice.getId());
}
// Initialize your member variable to be a
// CopyOnWriteArrayList with the above elements
brokerInvoiceLineItems = new CopyOnWriteArrayList<>(items);
// Iterate over the elements and possibly update the list from
// the fetchNewAndOldCFandAmend method
for (BrokerInvoiceLineItem brokerInvoiceLineItem : brokerInvoiceLineItems) {
if (fetchNewAndOldCFandAmend(brokerInvoiceLineItem)) {
if (!isAnyValid)
isAnyValid = true;
}
}
My code assumes that you have a class which stores a list of BrokerInvoiceLineItem and it's initialization is made in the constructor.
Usually it's a bad idea to iterate over a list and call another method which updates it. You can use an iterator to traverse it and remove certain elements. Your fetchNewAndOldCFandAmend
maybe can be used to indicate if the current item should be removed from the list and call the iterator's remove method.
Upvotes: 0
Reputation: 1615
I think you get this exception when you remove some items of brokerInvoiceLineItems
.
To avoid this exception, use an iterator
Iterator<BrokerInvoiceLineItem> iterator = brokerInvoiceLineItems.iterator();
while(iterator.hasNext()) {
BrokerInvoiceLineItem brokerInvoiceLineItem = iterator.next();
// your code
}
instead of
for (BrokerInvoiceLineItem brokerInvoiceLineItem : brokerInvoiceLineItems) {
so your code is:
Iterator<BrokerInvoiceLineItem> iterator = brokerInvoiceLineItems.iterator();
while(iterator.hasNext()) {
BrokerInvoiceLineItem brokerInvoiceLineItem = iterator.next();
if (fetchNewAndOldCFandAmend(brokerInvoiceLineItem)) {
if (!isAnyValid)
isAnyValid = true;
}
}
Upvotes: 1