java.util.ConcurrentModificationException in a Servlet



>编辑:我明白我的错误。我不知道为什么,但我在想,previousItems.add(p);执行后,它从for loop出去了。我已经通过添加一个break来解决

关于此异常的其他问题没有帮助我获得解决方案。

我有一个Servlet,当我从另一个页面在购物车中添加商品时调用。

我有一个ArrayList<Product>,我遍历列表以检查我尝试添加的相同产品是否已在列表中。如果它已经存在,我会更新其数量,否则我会在列表中添加新产品。

如果始终添加相同的产品,一切都很好,当我添加不同的产品时会发生异常。所以我认为代码中的问题在else之后(用"This"注释(,因为如果产品不同,它就会被执行。

@WebServlet(name = "AddCart", urlPatterns = {"/AddCart"})
public class AddCart extends HttpServlet {
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
HttpSession session = request.getSession();
ArrayList<Product> previousItems = (ArrayList<Product>) session.getAttribute("previousItems");
Product p = (Product) session.getAttribute("currentProduct");
if (previousItems == null) {
previousItems = new ArrayList<Product>();
}
if (p != null) {
if (previousItems.size()>0) {
for (Product p1 : previousItems) {
if (p1.getId() == p.getId()) {
p1.addQuantity();
} else { //This
previousItems.add(p);
}
}
} else {
previousItems.add(p);
}
}
session.setAttribute("previousItems", previousItems);
response.sendRedirect("cart.jsp");
}
}

我还尝试删除synchronized相同的异常。

这就是HTTP Status 500 – Internal Server Error

java.util.ConcurrentModificationException

java.util.ArrayList$Itr.checkForComodification(ArrayList.java:901( java.util.ArrayList$Itr.next(ArrayList.java:851( servlets。AddCart.doGet(AddCart.java:36( javax.servlet.http.HttpServlet.service(HttpServlet.java:635( javax.servlet.http.HttpServlet.service(HttpServlet.java:742( org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:52(

不能使用增强的 for 循环将项添加到正在迭代的列表中。这是因为您正在修改列表的内部状态;虽然可以处理这个问题,但大多数迭代器实现不处理底层集合的状态更改,以便为广大的绝大多数用例保持简单。

取而代之的是:

for (Product p1 : previousItems) {
previousItems.add(p); // Simplified
}

如果您希望p之后出现在列表中,请将其放入另一个列表中,然后在迭代后添加该列表:

List<Product> other = new ArrayList<>();
for (Product p1 : previousItems) {
other.add(p);
}
previousItems.addAll(other);

当您在循环中修改ArrayListfor会出现此异常。在内部,for循环使用Iterator,不允许在迭代期间修改非线程安全集合。您可以阅读本文以了解更多信息。

但是,我建议通过以下方式更改您的逻辑:

if (p != null) {
// Check if previousItems already contains the product
if (!previousItems.contains(p)) {
// If it doesn't, add the product
previousItems.add(p);
}
}

您无法更新正在迭代的列表,这会导致 ConcurrentModificationException

for (Product p1 : previousItems) {
previousItems.add(p); //you cant update the previousItems list here
}

相反,您可以做的是:

ArrayList<Product> auxList = new ArrayList<>();
for (Product p1 : previousItems) {
//...
//else...
auxList.add(p);
}

之后:

previousItems.addAll(auxList);

如果您只想避免 ConcurrentModificationException,请使用 CopyOnWriteArrayList 而不是 ArrayList。

最新更新