Come posso copiare in profondità una mappa delle mappe in Groovy? Le chiavi della mappa sono stringhe o int. I valori sono stringhe, oggetti primitivi o altre mappe, in modo ricorsivo.Copia profonda Mappa in Groovy
risposta
Un modo semplice è questa:
// 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()
}
Ho paura di doverlo fare nel modo clone
. Si potrebbe dare Apache Commons Lang SerializationUtils una prova
Sono abbastanza nuovo per Groovy. Potrei sbagliarmi. –
Il clone sembra funzionare bene per le mappe. Ma non appena porti oggetti più complicati sulla scena, non funziona altrettanto bene, perché è una copia poco profonda. La copia profonda di Ayman è veloce e funziona per gli oggetti che ho provato (incluso ConfigObject). – noumenon
ho appena colpito questo problema come bene, e ho appena trovato:
deepCopy = evaluate(original.inspect())
Anche se io Ho scritto codice in Groovy per meno di 12 ore, mi chiedo se ci potrebbero essere alcuni problemi di fiducia con l'utilizzo di evaluate
. Inoltre, quanto sopra non gestisce i backslash. Questo:
deepCopy = evaluate(original.inspect().replace('\\','\\\\'))
fa.
Grazie per aver menzionato l'ispezione. Ho cercato per anni un equivalente Groovy della repr di Python! Pensare che fosse sempre lì ... – Tobia
Ha funzionato per me quando modificai docker-compose.yml con groovy e jenkins. Grazie! (ha aggiunto questo commento per facilitare la ricerca su google) –
Per eseguire una copia completa di ciascun membro in una classe, esiste il newInstance() per gli oggetti di classe. Ad esempio,
foo = ["foo": 1, "bar": 2]
bar = foo.getClass().newInstance(foo)
foo["foo"] = 3
assert(bar["foo"] == 1)
assert(foo["foo"] == 3)
Vedi http://groovy-lang.org/gdk.html e passare a java.lang, classe, e, infine, il metodo sovraccarichi newInstance.
UPDATE:
L'esempio che ho sopra è in ultima analisi, un esempio di una copia, ma quello che veramente dire è che, in generale, si ha quasi sempre per definire la propria logica copia completa affidabile, con forse usando il metodo newInstance(), se il metodo clone() non è abbastanza. Ecco diversi modi come andare a tale proposito:
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)
ho usato @Canonical
per le equals() metodo e tuple ctor. Vedi groovy doc Chapter 3.4.2, Code Generation Transformations.
Un altro modo per eseguire la copia profonda è l'utilizzo di mix. Diciamo che si voleva una classe esistente per avere funzionalità copia profonda:
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])
o delle categorie (di nuovo vedere la groovy doc) se si voleva la semantica di copia profonde basata su una sorta di contesto di esecuzione:
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
- 1. copia profonda vs copia superficiale
- 2. JavaScript Object profonda copia
- 3. Copia profonda di un Drawable
- 4. profonda copia una struttura grafico
- 5. Copia profonda di array in Ruby
- 6. Copia profonda di array 2D in Scala?
- 7. copia profonda una lista in Python
- 8. Copia profonda di oggetti in Angular
- 9. Copia profonda di oggetti in angolare?
- 10. Scala AnyRef.clone esegue una copia poco profonda o profonda?
- 11. Tasti mappa rovesciata Groovy
- 12. Copia profonda in ES6 utilizzando il simbolo di diffusione
- 13. Scrittura di una copia profonda - copia del valore del puntatore
- 14. Copia profonda di un oggetto C#
- 15. Come creare manualmente una copia profonda
- 16. Copia profonda della serie di riferimenti PHP
- 17. costruttore di copia: una copia profonda di una classe astratta
- 18. mappa Groovy e mappa Java su generici
- 19. profonda duplice copia() di ByteBuffer di Java
- 20. Perché e quando usare angular.copy? (Copia profonda)
- 21. mappa Groovy errore di sintassi
- 22. Passa attraverso la mappa in Groovy?
- 23. Come eseguire una copia profonda di un InputStream in Java
- 24. env.Clone() in scons non esegue una copia profonda
- 25. Perché non c'è un metodo di copia profonda in Ruby?
- 26. Copia profonda di una matrice in Angular 2 + TypeScript
- 27. Come posso clonare un oggetto (copia profonda) in Dart?
- 28. Copia profonda quando si utilizza ArrayList in java
- 29. Il metodo clone su array è una copia profonda o poco profonda?
- 30. copia dei riferimenti una mappa in Java
Superbo. Sto usando questo per copiare in profondità un ConfigObject groovy come clone() fa solo una copia superficiale. La copia superficiale non è sufficiente su un ConfigObject per le mie esigenze. Grazie. – noumenon
Questo è abbastanza sorprendente –
Devo ricordarlo! –