日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程语言 > java >内容正文

java

Java中ListE对象赋值问题(引用传递和值传递)

發布時間:2025/3/18 java 19 豆豆
生活随笔 收集整理的這篇文章主要介紹了 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操作時,它同時會修改這個初始標記值,一直讓這個初始標記值等于當前標記值,程序結束后判斷兩者相等,就不會有異常!

private static void appendStock(Map<String,Object> busMap, List<Map<String, Object>> stocks , String key){if (stocks != null)for (Map<String,Object> s : stocks ) {boolean b = false;for (Map.Entry<String, Object> e : busMap.entrySet()) {if (s.get("stock_code") != null)if (s.get("stock_code").toString().equals(e.getKey())) {b = true;break;}}if ( !b ){stocks.remove(s);}} }

代碼② 修正foreach中remove異常,bug版
bug:
執行該方法后,stocks并沒有改變!!
原因:
對象引用傳遞導致。這個stocks是形參,他會復制外界的引用,也就是說這個stocks和外界的stocks不是同一個引用,但是指向同一個內存地址。所以只要stocks指向的對象修改了,外界對象(同一個對象)也隨著修改。但是這個stocks是形參,是一個新的變量,生命周期只存在于該方法體內,所以代碼最后stocks = newStocks沒有任何意義,因為調用方法結束,newStocks和stocks都會被GC干掉,外界對象引用地址是沒有發生一點變化的。唯獨變化的就是外界對象的另一個引用(就是方法中的stocks)在方法中對其的修改!這就告訴我們一個道理:在設計方法是void還是return的時候,要看看外界引用是否需要被重新賦值。如果需要,則return,否則void。也就是void方法只是對外界對象的堆內存操作。return對象多了可以對外界對象引用的修改優勢,但是這要加大開銷!

private static void 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;}}}stocks = newStocks; }

代碼③ 繞開改變外界引用,穩定版
采用Iterator來刪除元素,摒棄拷貝,從而不入淺拷貝的坑

private static void appendStock(Map<String,Object> busMap, List<Map<String, Object>> stocks , String key){if (stocks != null && stocks.size() > 0) {Iterator<Map<String, Object>> iterator = stocks.iterator();while (iterator.hasNext()) {Map<String, Object> s = iterator.next();if (s.get("stock_code") != null) {String stockCode = String.valueOf(s.get("stock_code"));if ( !busMap.containsKey(stockCode)) {iterator.remove();}}}} }

代碼④返回引用賦值給外界引用,穩定版

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对象赋值问题(引用传递和值传递)的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。