Servlet中的java.util.ConcurrentModificationException

时间:2017-08-12 19:12:26

标签: java servlets arraylist collections iterator

编辑:我理解我的错误。我不知道为什么,但我认为previousItems.add(p);执行后它会从for loop出来。我通过添加break

解决了这个问题

关于此例外的其他问题并没有帮助我找到解决方案。

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

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

如果总是添加相同的产品,一切都很好,当我添加不同的产品时会发生异常。所以我认为代码中的问题出现在else之后(注释了&#34; This&#34;),因为如果产品不同,它就会被执行。

@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)

  

4 个答案:

答案 0 :(得分:3)

您无法将项目添加到使用增强型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);

答案 1 :(得分:1)

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

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

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

答案 2 :(得分:1)

您无法更新正在迭代的列表,这会导致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);

答案 3 :(得分:0)

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