說說java中傳容器某些情況下失效
樓主今天寫個方法移除map集合中的空值,遇到個問題,就是對容器操作後,發現失效了;先上程式碼
public static void removeValueNullAndEmpty(Map<String,String> A) { Map<String,String> B = new HashMap<>(); for(String key : B.keySet()){ if(A.get(key) != null || !"".equals(A.get(key))){ B.put(key, A.get(key)); } } A=B; } public static void main(String[] args) { Map<String,String> B = new HashMap<>(); B.put("c", "3"); B.put("d", ""); B.put("e", null); removeValueNullAndEmpty(B); System.out.println(B); }
就是這麼個操作,結果當然很尷尬;
{c=3, d=, e=null}
怎麼回事呢?這就要說到函式的呼叫了,在main函式呼叫removeValueNullAndEmpty的時候,儲存現場,儲存了B的地址;我們姑且看做addressB吧,也就是說main函式任務B = addressB;然後就把addressB傳給了removeValueNullAndEmpty方法,而removeValueNullAndEmpty方法的一系列處理其實並沒有改變addressB這個地址指向的空間內的任何資料;而是簡單的把B這個字面量指向的地址換成了addressB;然後結束了removeValueNullAndEmpty方法;在此之後,回到main方法,而main方法依然認為B = addressB,為什麼呢?這是因為我們在removeValueNullAndEmpty方法中改變的那個字面量B已經隨著removeValueNullAndEmpty方法的結束而被關閉了,根本就和main方法沒有任何關係,所以main方法下面的輸出語句依然會輸出addressB所指向空間內的值。就是這麼簡單。
找到了問題自然要解決啊,但是我又不想通過return來返回,就是希望B這個map過一趟removeValueNullAndEmpty方法就把沒用的東西給丟掉了;怎麼辦呢?我首先是在原來的程式碼上隨便做了點修改
public static void removeValueNullAndEmpty(Map<String,String> A) { for(String key : A.keySet()){ if(A.get(key) == null || "".equals(A.get(key))){ A.remove(key); } } }
這樣當然不行了,一執行就報錯了
Exception in thread "main" java.util.ConcurrentModificationException at java.util.HashMap$HashIterator.nextNode(Unknown Source) at java.util.HashMap$KeyIterator.next(Unknown Source) at test.Main.removeValueNullAndEmpty(Main.java:28) at test.Main.main(Main.java:52)
這一看就曉得了,keySet()拿出來的是個set檢視,這只是一個與map中鍵的對映;如果remove掉原map集合中的一個元素,就會影響到keySet()取到的set檢視的內容,進而影響到後續元素的獲取,所以這麼做是不被允許的,那麼只能想其他辦法了。這時候,我想到了迭代器
public static void removeValueNullAndEmpty(Map<String,String> A) { Iterator<String> iterator = A.keySet().iterator(); while (iterator.hasNext()) { String key = iterator.next(); if(A.get(key) == null || "".equals(A.get(key))){ iterator.remove(); } } } public static void main(String[] args) { Map<String,String> B = new HashMap<>(); B.put("c", "3"); B.put("d", ""); B.put("e", null); removeValueNullAndEmpty(B); System.out.println(B); }
執行之後,就灰常正常了。
{c=3}
ok,其實不是多大的問題,主要是對集合不熟悉的鍋就這樣吧