今天在碼代碼的時候出現一個沒有預料的問題:
先看下面的代碼:
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理解不深導致
