問題:map拷貝時發現資料會變化。
高能預警,你看到的下面的栗子是不正確的,後面有正確的一種辦法,如果需要看的話的,請看到底,感謝各同學的提醒,已做更正,一定要看到最後
先看例子:
publicclasscopymap
}上面程式的期望輸出值是,mapfrist的值均為1,
但是實際上輸出結果為:
這裡是因為map發生了淺拷貝,mapfirst只是複製了map的引用,和map仍使用同乙個記憶體區域,所以,在修改map的時候,mapfirst的值同樣會發生變化。
ps:所謂淺複製:則是只複製物件的引用,兩個引用仍然指向同乙個物件,在記憶體中占用同一塊記憶體。被複製物件的所有變數都含有與原來的物件相同的值,而所有的對其他物件的引用仍然指向原來的物件。換言之,淺複製僅僅複製所考慮的物件,而不複製它所引用的物件。
深複製:被複製物件的所有變數都含有與原來的物件相同的值,除去那些引用其他物件的變數。那些引用其他物件的變數將指向被複製過的新物件,而不再是原有的那些被引用的物件。換言之,深複製把要複製的物件所引用的物件都複製了一遍。
如何解決?
使用深拷貝,拷貝整個物件,而非引用
map中有個方法叫做putall方法,可以實現深拷貝,如下:
publicclasscopymap
}如上,輸出結果為:
參考:注意!!!注意!!!!注意!!! 上面並不是深拷貝,留下來的原因是提醒大家,這裡是存在錯誤的。(很高興你看到這裡了)
感謝下面這幾位朋友的提醒。
如何實現map的深拷貝呢?
有一種方法,是使用序列化的方式來實現物件的深拷貝,但是前提是,物件必須是實現了serializable介面才可以,map本身沒有實現 serializable 這個介面,所以這種方式不能序列化map,也就是不能深拷貝map。但是hashmap是可以的,因為它實現了 serializable。下面的方式,基於hashmap來講,非map的拷貝。
具體實現如下:
01
public
class
cloneutils
catch
(exception e)
21
22
return
clonedobj;
23
}
24
}
如何使用呢,下面是個使用的例子,同時證明了map的putall方法並沒有實現深拷貝,putall僅對基本資料型別起到深拷貝的作用。
栗子:01
public
static
void
main(string args)
輸出結果如下:
最上面的兩條是原始資料,使用了putall方法拷貝了乙個新的mapnew物件,
中間兩條,是修改map物件的基本資料型別的時候,並沒有影響到mapnew物件。
但是看倒數第二組,更改引用資料型別的時候,發現mapnew的值也變化了,所以putall並沒有對map產生深拷貝。
最後面是使用序列化的方式,發現,更改引用型別的資料的時候,mapnew物件並沒有發生變化,所以產生了深拷貝。
上述的工具類,可以實現物件的深拷貝,不僅限於hashmap,前提是實現了serlizeable介面。
還沒有看putall的原始碼實現,後面看下為什麼不能實現深拷貝。
Map物件的淺拷貝與深拷貝
問題 map拷貝時發現資料會變化。先看例子 public class copymap 上面程式的期望輸出值是,mapfrist的值均為1,但是實際上輸出結果為 這裡是因為map發生了淺拷貝,mapfirst只是複製了map的引用,和map仍使用同乙個記憶體區域,所以,在修改map的時候,mapfir...
js 物件深拷貝 深拷貝與淺拷貝
前言 最近在複習一些面試的知識點,剛剛好複習到了這一部分,於是就寫下這篇文章記錄一下。一 值型別和引用型別 在學習深拷貝和淺拷貝之前,我們先來了解一下js的變數型別。值型別 vs 引用型別 值型別 值型別主要有 number,string,boolean,symbol,null,undefined ...
java 複製Map物件(深拷貝與淺拷貝)
淺拷貝 只複製物件的引用,兩個引用仍然指向同乙個物件,在記憶體中占用同一塊記憶體 被複製物件的所有變數都含有與原來的物件相同的值,而所有的對其他物件的引用仍然指向原來的物件 換言之,淺複製僅僅複製所考慮的物件,而不複製它所引用的物件。深拷貝 被複製物件的所有變數都含有與原來的物件相同的值,除去那些引...