Java中ListE对象赋值问题(引用传递和值传递)
Java中List<E>對象賦值操作問題
業務需求是:取2個集合中的交集對象并返回。如下代碼,busMap中key值和stocks中Map中的key值相等的對象則返回繼續操作,也就是說剔除stocks中的不存在于busMap中的對象,就是一個過濾操作。
實現代碼 ① bug版
報錯:
java.util.ConcurrentModificationException ; at java.util.ArrayList$Itr.checkForComodification(ArrayList.java:859) ; at java.util.ArrayList$Itr.next(ArrayList.java:831) ;
原因:
forEach實現是采用Iterator實現的,而remove操作不能在Iterator下操作,所以報錯,具體原因是Iterator遍歷開始前,會對該對象生成一個改變前的標記值,在進行map.remove操作的時候,改變了這個值,導致循環結束后,程序檢查初始標記和結束標記不一致,就報錯了。而使用Iterator.remove操作時,它同時會修改這個初始標記值,一直讓這個初始標記值等于當前標記值,程序結束后判斷兩者相等,就不會有異常!
代碼② 修正foreach中remove異常,bug版
bug:
執行該方法后,stocks并沒有改變!!
原因:
對象引用傳遞導致。這個stocks是形參,他會復制外界的引用,也就是說這個stocks和外界的stocks不是同一個引用,但是指向同一個內存地址。所以只要stocks指向的對象修改了,外界對象(同一個對象)也隨著修改。但是這個stocks是形參,是一個新的變量,生命周期只存在于該方法體內,所以代碼最后stocks = newStocks沒有任何意義,因為調用方法結束,newStocks和stocks都會被GC干掉,外界對象引用地址是沒有發生一點變化的。唯獨變化的就是外界對象的另一個引用(就是方法中的stocks)在方法中對其的修改!這就告訴我們一個道理:在設計方法是void還是return的時候,要看看外界引用是否需要被重新賦值。如果需要,則return,否則void。也就是void方法只是對外界對象的堆內存操作。return對象多了可以對外界對象引用的修改優勢,但是這要加大開銷!
代碼③ 繞開改變外界引用,穩定版
采用Iterator來刪除元素,摒棄拷貝,從而不入淺拷貝的坑
代碼④返回引用賦值給外界引用,穩定版
private static List<Map<String, Object>> appendStock(Map<String,Object> busMap, List<Map<String, Object>> stocks , String key){if (stocks != null)List<Map<String,Object>> newStocks = Lists.newArrayList(); // 構建新對象保存交集數據for (Map<String,Object> s : stocks ) {for (Map.Entry<String, Object> e : busMap.entrySet()) {if (s.get("stock_code") != null)if (s.get("stock_code").toString().equals(e.getKey())) {newstocks.add(s);break;}}}return newStocks; }轉載于:https://blog.51cto.com/11939788/2162805
總結
以上是生活随笔為你收集整理的Java中ListE对象赋值问题(引用传递和值传递)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: MySql之自动同步表结构
- 下一篇: 关于FlexBox的布局