Deep copying Java objects with circular references -



Deep copying Java objects with circular references -

how go implementing deep re-create foo? contains instance of bar, has reference foo.

public class foo { bar bar; foo () { bar = new bar(this); } foo (foo oldfoo) { bar = new bar(oldfoo.bar); } public static void main(string[] args) { foo foo = new foo(); foo newfoo = new foo(foo); } class bar { foo foo; bar (foo foo) { this.foo = foo; } bar (bar oldbar) { foo = newfoo(oldbar.foo); } } }

as stands, code cause stack overflow due infinite recursion.

also, simplistic illustration construct. in practice, object graph larger, multiple instance variables collections. think multiple bars, multiple foos, instance.

edit: i'm in process of implementing @chiastic-security's method. doing correctly foo? i'm using separate hashmap contain parts of object graph can write deep re-create functionality possible.

foo (foo oldfoo) throws exception { this(oldfoo, new identityhashmap<object, object>(), new identityhashset<object>()); } foo (foo oldfoo, identityhashmap<object, object> clonedobjects, identityhashset<object> cloning) throws exception { system.out.println("copying foo"); hashmap<object, object> newtooldobjectgraph = new hashmap<object, object>(); newtooldobjectgraph.put(bar, oldfoo.bar); deepcopy(newtooldobjectgraph, clonedobjects, cloning); } void deepcopy(hashmap<object, object> newtooldobjectgraph, identityhashmap<object, object> clonedobjects, identityhashset<object> cloning) throws exception { (entry<object, object> entry : newtooldobjectgraph.entryset()) { object newobj = entry.getkey(); object oldobj = entry.getvalue(); if (clonedobjects.containskey(oldobj)) { newobj = clonedobjects.get(oldobj); } else if (cloning.contains(oldobj)){ newobj = null; } else { cloning.add(oldobj); // recursively deep clone newobj = newobj.getclass().getconstructor(oldobj.getclass(), clonedobjects.getclass(), cloning.getclass()). newinstance(oldobj, clonedobjects, cloning); clonedobjects.put(oldobj, newobj); cloning.remove(oldobj); } if (newobj == null && clonedobjects.containskey(oldobj)) { newobj = clonedobjects.get(oldobj); } } }

the easiest way implement deep re-create might involve circular references, if want tolerant of changes construction later, utilize identityhashmap , identityhashset (from here). when want copy:

create empty identityhashmap<object,object>, map source objects clones. create empty identityhashset<object> track objects in process of beingness cloned, haven't yet finished. start re-create process going. @ each stage, when want re-create object, in identityhashmap see if you've cloned bit. if have, homecoming re-create find in identityhashmap. check in identityhashset see if you're in middle of cloning object you've reached (because of circular reference). if have, set null now, , move on. if haven't cloned (i.e., source object isn't in map), , you're not in middle of cloning (i.e., it's not in set), add together identityhashset, recursively deep clone it, , when you've finished recursive call, add together source/clone pair identityhashmap, , remove identityhashset. now @ end of recursive cloning, need deal null references left hanging because encountered circular reference. can walk graph of source , destination simultaneously. whenever find object in source graph, in identityhashmap, , find out should map to. if exists in identityhashmap, , if it's null in destination graph, can set destination reference clone find in identityhashmap.

this create sure don't clone same part of graph twice, end same reference whenever there's object appears twice in graph. mean circular references don't cause infinite recursion.

the point of using identity versions if 2 objects in graph same determined .equals(), different instances determined ==, hashset , hashmap identify two, , you'd end joining things shouldn't joined. identity versions treat 2 instances same if they're identical, i.e., same determined ==.

if want without having implement yourself, have @ java deep cloning library.

java

Comments

Popular posts from this blog

java Multi query from Mysql using netbeans -

c# - DotNetZip fails with "stream does not support seek operations" -

c++ - StartServiceCtrlDispatcher don't can access 1063 error -