我在片場的這個迭代器有問題。這是我使用 spring Initializer 創建的一個小專案。
我使用帶有tomcat的spring boot。以前我使用了一個 for 回圈,然后我在這里看到了這個答案迭代一個集合,在回圈中洗掉物件時避免 ConcurrentModificationException并嘗試使第一個答案適應我的情況。
唯一的問題是我必須在洗掉之前將 2 個物體 Parent 和 Child 從雙向一對多、多對一關系中分離出來。即使我使用迭代器,我仍然會收到此錯誤。
@PostMapping("/savecart")
public ResponseEntity<String> saveCartToDb(@RequestBody Set<CartProduct> cartProductList, Principal principal) {
User logedInUser = userService.findUserByUsername(principal.getName()).get();
Set<CartProduct> cartItemList = logedInUser.getCartProduct();
for (CartProduct cartProduct : cartProductList) {
cartProduct.setUser(logedInUser);
}
userService.saveNewUser(logedInUser);
log.info("In saveCartToDb()");
if (cartItemList.isEmpty()) {
logedInUser.setCartProduct(cartProductList);
userService.saveNewUser(logedInUser);
} else {
for (Iterator<CartProduct> iterator = cartItemList.iterator(); iterator.hasNext();) {
CartProduct cartItem = iterator.next();
if (cartItem != null) {
// Remove the current element from the iterator and the list.
cartItem.dismissParent();
logedInUser.dismissChild(cartItem);
iterator.remove();
userService.saveNewUser(logedInUser);
}
}
// for(CartProduct cartItem : cartItemList){
// cartItem.dismissParent();
// logedInUser.dismissChild(cartItem);
// userService.saveNewUser(logedInUser);
// }
cartProductService.deleteAllProductIds();
for (CartProduct cartProduct : cartProductList) {
cartProduct.setUser(logedInUser);
}
logedInUser.setCartProduct(cartProductList);
userService.saveNewUser(logedInUser);
}
return ResponseEntity.ok().body(cartProductList.toString());
}
我用來解耦的方法
public void dismissChild(CartProduct child) {
this.cartProduct.remove(child);
}
public void dismissParent() {
this.user.dismissChild(this);
this.user = null;
}
java.util.ConcurrentModificationException: null
at java.base/java.util.HashMap$HashIterator.remove(HashMap.java:1611) ~[na:na]
有沒有辦法可以修改迭代器不再收到此錯誤?還是使用迭代器有更好的解決方案?
uj5u.com熱心網友回復:
根據你的例外
java.util.ConcurrentModificationException: null
at java.base/java.util.HashMap$HashIterator.remove(HashMap.java:1611) [na:na]
因此,您使用了 aHashMap并且收到了ConcurrentModificationException.
但是等一下,您的代碼中沒有任何HashMap靠近錯誤的地方嗎?
你有cartItemList.iterator()并且cartItemList被宣告為Set<CartProduct>. 此外,您提供的實作將是HashSet.
但是HashSet是通過java使用HashMap. 因此,您提到的錯誤是HashMap.
從檔案
公共類ConcurrentModificationException擴展 RuntimeException
當這種修改是不允許的時,檢測到物件的并發修改的方法可能會拋出此例外。例如,通常不允許一個執行緒在另一個執行緒對其進行迭代時修改 Collection。一般來說,在這些情況下,迭代的結果是不確定的。如果檢測到此行為,某些迭代器實作(包括 JRE 提供的所有通用集合實作的那些)可能會選擇拋出此例外。這樣做的迭代器被稱為快速失敗迭代器,因為它們快速而干凈地失敗,而不是在未來不確定的時間冒著任意的、非確定性的行為的風險。
請注意,此例外并不總是表明物件已被不同的執行緒同時修改。如果單個執行緒發出一系列違反物件約定的方法呼叫,則該物件可能會拋出此例外。例如,如果執行緒在使用快速失敗迭代器迭代集合時直接修改集合,則迭代器將拋出此例外。
HashMap并且還HashSet提供了一個快速失敗的迭代器,這意味著您不允許在迭代期間修改集合。
要解決您的問題,您應該避免在迭代期間修改集合。
所以下面的代碼塊
for (Iterator<CartProduct> iterator = cartItemList.iterator(); iterator.hasNext();) {
CartProduct cartItem = iterator.next();
if (cartItem != null) {
// Remove the current element from the iterator and the list.
cartItem.dismissParent();
logedInUser.dismissChild(cartItem);
iterator.remove();
userService.saveNewUser(logedInUser);
}
}
可以改寫為
List<CartProduct> toBeRemoved = new ArrayList(); <-----------
for (Iterator<CartProduct> iterator = cartItemList.iterator(); iterator.hasNext();) {
CartProduct cartItem = iterator.next();
if (cartItem != null) {
// Remove the current element from the iterator and the list.
cartItem.dismissParent();
logedInUser.dismissChild(cartItem);
toBeRemoved.add(cartItem); <---------------
userService.saveNewUser(logedInUser);
}
}
cartItemList.removeAll(toBeRemoved); <--------
因此,您只需在迭代期間收集所有需要洗掉的元素,并且僅在迭代后呼叫洗掉。
轉載請註明出處,本文鏈接:https://www.uj5u.com/net/520993.html
