今天在碼代碼的時候出現一個沒有預料的問題:
先看下面的代碼:
public static void main(String[] args) { String[] files=new String[]{"abcd","qwer","asdf"}; Map<String,Object> map=new HashMap<String,Object>(); map.put("file", "12345"); map.put("id", 15); map.put("name", "works"); List<Map<String,Object>> list=new ArrayList<Map<String,Object>>(); for (int i = 0; i < files.length; i++) { list.add(map); list.get(i).put("file", files[i]); } System.out.println(list.toString()); }
這里map模擬從數據庫取到的一條記錄,我的本意是根據files的大小生成一個包含n個map的List<Map<String,Object>,list中map的其他key的值都不變,只有key為file的值須要替換為files數組內的內容,於是大致寫了上述的處理代碼,咋一看上去沒有任何問題。運行之后發現,list中的每一個map中key為file的value都為“asdf” !這是什么問題呢,換了多種方法處理,例如,先生成list,再遍歷list進行修改,可是結果沒有任何變化,超出預期!
[{id=15, file=asdf, name=works}, {id=15, file=asdf, name=works}, {id=15, file=asdf, name=works}]
折騰好久,終於發現問題:其實list中的所有元素(map)的引用都是指向內存中的同一塊區域,所以上述的修改方式,最終會變成上述輸出。
處理辦法:
public static void main(String[] args) { String[] files=new String[]{"abcd","qwer","asdf"}; Map<String,Object> map=new HashMap<String,Object>(); map.put("file", "12345"); map.put("id", 15); map.put("name", "works"); List<Map<String,Object>> list=new ArrayList<Map<String,Object>>(); for (int i = 0; i < files.length; i++) { Map<String,Object> hmp=new HashMap<String,Object>(); Iterator<String> it=map.keySet().iterator(); while (it.hasNext()) { String key = (String) it.next(); hmp.put(key, map.get(key)); } list.add(hmp); list.get(i).put("file", files[i]); } System.out.println(list.toString()); }
這樣做的目的是每次都new一個Map對象hmp,然后把原來map中的內容復制到新的Map對象中,那么list中的map對象便是分別擁有不同的存儲區域。然后對key對應的value進行修改時便不會出現之前被覆蓋的問題了。
[{id=15, file=abcd, name=works}, {id=15, file=qwer, name=works}, {id=15, file=asdf, name=works}]
出現這個問題,主要是對內存/對象的引用以及Map的相關API理解不深導致