我有下面的java代码抛出ConcurrentModificationException
下面是java代码
下面是要声明的列表
List<BrokerInvoiceLineItem> brokerInvoiceLineItems= new ArrayList<BrokerInvoiceLineItem>();
brokerInvoiceLineItems=brokerInvoice.getLineItems();
下面的是抛出concurrentmodification异常
的那段代码if (brokerInvoiceLineItems == null) {
brokerInvoiceLineItems = brokerInvoiceHome.findLineitemsByInvoiceId(brokerInvoice.getId());
}
for (BrokerInvoiceLineItem brokerInvoiceLineItem : brokerInvoiceLineItems) {
if (fetchNewAndOldCFandAmend(brokerInvoiceLineItem)) {
if (!isAnyValid)
isAnyValid = true;
}
}
现在的问题是,如果brokerinvoiceineitems不为null那么对于第一次迭代,它将进入循环并且变量isAnyValid的值设置为true但是一旦第一次迭代结束那么对于第二次迭代,它将再次进入for (BrokerInvoiceLineItem brokerInvoiceLineItem : brokerInvoiceLineItems){
行然后它不会进入下一行它抛出并发修改异常
所以这意味着它必须在迭代时修改brokerinvoiceineitems的大小。这可能发生在fetchNewAndOldCFandAmend
,所以我正在考虑制作brokerinvoiceineitems的副本并修改副本。所以请告诉我如何将副本传递给fetchNewAndOldCFandAmend(brokerInvoiceLineItem)
还请告知如何使用copyonwriteArray列表也避免这样的错误
我认为当你删除brokerInvoiceLineItems
的一些项目时,你会得到这个异常。
要避免此异常,使用迭代器
Iterator<BrokerInvoiceLineItem> iterator = brokerInvoiceLineItems.iterator();
while(iterator.hasNext()) {
BrokerInvoiceLineItem brokerInvoiceLineItem = iterator.next();
// your code
}
代替
for (BrokerInvoiceLineItem brokerInvoiceLineItem : brokerInvoiceLineItems) {
所以你的代码是:
Iterator<BrokerInvoiceLineItem> iterator = brokerInvoiceLineItems.iterator();
while(iterator.hasNext()) {
BrokerInvoiceLineItem brokerInvoiceLineItem = iterator.next();
if (fetchNewAndOldCFandAmend(brokerInvoiceLineItem)) {
if (!isAnyValid)
isAnyValid = true;
}
}
我假设您正在修改fetchNewAndOldCFandAmend
方法中的brokerInvoiceLineItems
。你可以使用CopyOnWriteArrayList而不是ArrayList。这允许您迭代列表并同时更新它。这是有代价的,因为每次你向它添加东西时,它都会创建一个新的数组。示例代码如下所示:
// 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;
}
}
我的代码假设您有一个类,该类存储brokerinvoiceineitem的列表,并且它的初始化是在构造函数中进行的。
迭代一个列表并调用另一个方法来更新它通常不是一个好主意。可以使用迭代器遍历它并删除某些元素。你的fetchNewAndOldCFandAmend
也许可以用来指示当前项是否应该从列表中删除,并调用迭代器的remove方法。
你应该创建一个新的数组列表,并将之前的数组列表对象的所有元素添加到其中。
ArrayList<BrokerInvoiceLineItem> otherList = new ArrayList<BrokerInvoiceLineItem>();
otherList.addAll(brokerInvoiceLineItems);
注意:如果您将for语句更改为另一个语句,如:
for(int i=0;i<brokerInvoiceLineItems.size();i++){
你不会得到ConcurrentModificationException。
更新:示例代码:
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;
}
}