2012-10-31 18 views
10

में डीप कॉपी मानचित्र कैसे मैं गहरी ग्रूवी में नक्शे का एक नक्शा कॉपी कर सकते हैं? नक्शा कुंजी स्ट्रिंग्स या इंट्स हैं। मूल्य एक पुनरावर्ती तरीके से स्ट्रिंग्स, आदिम ऑब्जेक्ट्स या अन्य मानचित्र हैं।ग्रूवी

उत्तर

21

एक आसान तरीका यह है सकता है:

// standard deep copy implementation 
def deepcopy(orig) { 
    bos = new ByteArrayOutputStream() 
    oos = new ObjectOutputStream(bos) 
    oos.writeObject(orig); oos.flush() 
    bin = new ByteArrayInputStream(bos.toByteArray()) 
    ois = new ObjectInputStream(bin) 
    return ois.readObject() 
} 
+0

शानदार। मैं इसे गहरी प्रतिलिपि बनाने के लिए उपयोग कर रहा हूं क्योंकि क्लोन() केवल क्लोन() केवल एक उथली प्रतिलिपि करता है। मेरी आवश्यकताओं के लिए Defowbject पर उथली प्रति पर्याप्त नहीं है। धन्यवाद। – noumenon

+0

यह सुंदर अद्भुत –

+0

गोना इस याद करने के लिए किया है! –

2

मुझे डर है कि आप इसे clone तरह से क्या करना है कर रहा हूँ। आप अपाचे कॉमन्स लैंग SerializationUtils देना एक कोशिश

+0

मैं कर रहा हूँ मान लीजिए कि आप गहरी प्रतिलिपि कार्यक्षमता के लिए एक मौजूदा वर्ग चाहता था चलो ग्रोवी के लिए बहुत नया है। मै गलत हो सकता हूँ। –

+0

क्लोन नक्शे के लिए अच्छी तरह से काम करता प्रतीत होता है। लेकिन जैसे ही आप दृश्य पर अधिक जटिल वस्तुएं लाते हैं, यह भी काम नहीं करता है, क्योंकि यह एक उथली प्रतिलिपि है। अयमान की गहरी प्रतिलिपि तेज़ है और उन वस्तुओं के लिए काम करती है जिन्हें मैंने कोशिश की (ConfigObject सहित)। – noumenon

4

मैं सिर्फ इस मुद्दे के रूप में अच्छी तरह से मारा गया है, और मैं सिर्फ पाया:

deepCopy = evaluate(original.inspect()) 

हालांकि मैं 'कम से कम 12 घंटे के लिए ग्रूवी में कोडिंग किया गया है, मुझे आश्चर्य है कि अगर वहाँ evaluate का उपयोग कर के साथ कुछ विश्वास मुद्दों हो सकता है। इसके अलावा, उपरोक्त बैकस्लाश को संभाल नहीं करता है। यह:

deepCopy = evaluate(original.inspect().replace('\\','\\\\')) 

करता है।

+0

निरीक्षण का उल्लेख करने के लिए धन्यवाद। मैंने पाइथन के रिप्र के समतुल्य ग्रोवी के लिए उम्र की तलाश की है! यह सोचने के लिए कि यह सब कुछ था ... – Tobia

+1

groovy और जेनकिंस के साथ docker-compose.yml संपादित करते समय मेरे लिए काम किया। धन्यवाद! (आसान गूगल खोज के लिए इस टिप्पणी को जोड़ा) –

3

गहरी नकल के बारे में एक कक्षा में प्रत्येक सदस्य जाने के लिए, newInstance() वर्ग वस्तुओं के लिए मौजूद है। उदाहरण के लिए,

foo = ["foo": 1, "bar": 2] 
bar = foo.getClass().newInstance(foo) 
foo["foo"] = 3 
assert(bar["foo"] == 1) 
assert(foo["foo"] == 3) 

http://groovy-lang.org/gdk.html देखें और java.lang, कक्षा, और अंत में newInstance विधि भार के पर जाएँ।

अद्यतन:

उदाहरण मैं ऊपर है अंततः एक उथले नकल का एक उदाहरण है, लेकिन क्या मैं वास्तव में मतलब था सामान्य रूप में, आप लगभग हमेशा के साथ अपने स्वयं विश्वसनीय गहरी प्रतिलिपि तर्क को परिभाषित करने, है शायद newInstance() विधि का उपयोग कर, अगर क्लोन() विधि पर्याप्त नहीं है। यहाँ कई तरीके कैसे इस बारे में जाने के लिए है:

import groovy.transform.Canonical 
import groovy.transform.AutoClone 
import static groovy.transform.AutoCloneStyle.* 

// in @AutoClone, generally the semantics are 
// 1. clone() is called if property implements Cloneable else, 
// 2. initialize property with assignment, IOW copy by reference 
// 
// @AutoClone default is to call super.clone() then clone() on each property. 
// 
// @AutoClone(style=COPY_CONSTRUCTOR) which will call the copy ctor in a 
// clone() method. Use if you have final members. 
// 
// @AutoClone(style=SIMPLE) will call no arg ctor then set the properties 
// 
// @AutoClone(style=SERIALIZATION) class must implement Serializable or 
// Externalizable. Fields cannot be final. Immutable classes are cloned. 
// Generally slower. 
// 
// if you need reliable deep copying, define your own clone() method 

def assert_diffs(a, b) { 
    assert a == b // equal objects 
    assert ! a.is(b) // not the same reference/identity 
    assert ! a.s.is(b.s) // String deep copy 
    assert ! a.i.is(b.i) // Integer deep copy 
    assert ! a.l.is(b.l) // non-identical list member 
    assert ! a.l[0].is(b.l[0]) // list element deep copy 
    assert ! a.m.is(b.m) // non-identical map member 
    assert ! a.m['mu'].is(b.m['mu']) // map element deep copy 
} 

// deep copy using serialization with @AutoClone 
@Canonical 
@AutoClone(style=SERIALIZATION) 
class Bar implements Serializable { 
    String s 
    Integer i 
    def l = [] 
    def m = [:] 

    // if you need special serialization/deserialization logic override 
    // writeObject() and/or readObject() in class implementing Serializable: 
    // 
    // private void writeObject(ObjectOutputStream oos) throws IOException { 
    // oos.writeObject(s) 
    // oos.writeObject(i) 
    // oos.writeObject(l) 
    // oos.writeObject(m) 
    // } 
    // 
    // private void readObject(ObjectInputStream ois) 
    // throws IOException, ClassNotFoundException { 
    // s = ois.readObject() 
    // i = ois.readObject() 
    // l = ois.readObject() 
    // m = ois.readObject() 
    // } 
} 

// deep copy by using default @AutoClone semantics and overriding 
// clone() method 
@Canonical 
@AutoClone 
class Baz { 
    String s 
    Integer i 
    def l = [] 
    def m = [:] 

    def clone() { 
     def cp = super.clone() 
     cp.s = s.class.newInstance(s) 
     cp.i = i.class.newInstance(i) 
     cp.l = cp.l.collect { it.getClass().newInstance(it) } 
     cp.m = cp.m.collectEntries { k, v -> 
     [k.getClass().newInstance(k), v.getClass().newInstance(v)] 
     } 
     cp 
    } 
} 

// assert differences 
def a = new Bar("foo", 10, ['bar', 'baz'], [mu: 1, qux: 2]) 
def b = a.clone() 
assert_diffs(a, b) 

a = new Baz("foo", 10, ['bar', 'baz'], [mu: 1, qux: 2]) 
b = a.clone() 
assert_diffs(a, b) 

मैं बराबर() विधि और टपल ctor के लिए @Canonical इस्तेमाल किया। groovy doc Chapter 3.4.2, Code Generation Transformations देखें।

गहरी नकल के बारे में जाने के लिए mixins उपयोग कर रहा है एक और तरीका है।

class LinkedHashMapDeepCopy { 
    def deep_copy() { 
     collectEntries { k, v -> 
     [k.getClass().newInstance(k), v.getClass().newInstance(v)] 
     } 
    } 
} 

class ArrayListDeepCopy { 
    def deep_copy() { 
     collect { it.getClass().newInstance(it) } 
    } 
} 

LinkedHashMap.mixin(LinkedHashMapDeepCopy) 
ArrayList.mixin(ArrayListDeepCopy) 

def foo = [foo: 1, bar: 2] 
def bar = foo.deep_copy() 
assert foo == bar 
assert ! foo.is(bar) 
assert ! foo['foo'].is(bar['foo']) 

foo = ['foo', 'bar'] 
bar = foo.deep_copy() 
assert foo == bar 
assert ! foo.is(bar) 
assert ! foo[0].is(bar[0]) 

या श्रेणियों (फिर groovy doc देखें) यदि आप क्रम संदर्भ में किसी प्रकार का के आधार पर गहरी नकल अर्थ विज्ञान चाहता था:

import groovy.lang.Category 

@Category(ArrayList) 
class ArrayListDeepCopy { 
    def clone() { 
     collect { it.getClass().newInstance(it) } 
    } 
} 

use(ArrayListDeepCopy) { 
    def foo = ['foo', 'bar'] 
    def bar = foo.clone() 
    assert foo == bar 
    assert ! foo.is(bar) 
    assert ! foo[0].is(bar[0]) // deep copying semantics 
} 

def foo = ['foo', 'bar'] 
def bar = foo.clone() 
assert foo == bar 
assert ! foo.is(bar) 
assert foo[0].is(bar[0]) // back to shallow clone 
संबंधित मुद्दे