2017-02-06 2 views
0

Ich versuche im Grunde nur eine tiefe Kopie von Einsen und Nullen zu machen, also hätte ich booleans verwenden können, aber ich habe mich gefragt, wie man das für ganze Zahlen in general machen kann.Wie mache ich eine tiefe Kopie einer ArrayList <Integer> in Java?

private ArrayList<Integer> makeDeepCopyInteger(ArrayList<Integer> a) { 
    ArrayList<Integer> newA = new ArrayList<>(a.size()); 
    for (int i = 0; i < a.size(); i++) { 
     int newInt = 0; 
     if (a.get(i) == 1) { 
      newInt = 1; 
     } 
     newA.add(newInt); 
    } 
    return newA; 
} 
+10

Da Ganzzahlen unveränderlich sind, warum sollten Sie sie tief kopieren? –

Antwort

1

Die clone() Methode geschützt ist die Integer Klasse, so dass Sie Integer.clone() außerhalb dieser Klasse nicht aufrufen können. Was Sie stattdessen tun können, ist ein new Integer erstellen.

private ArrayList<Integer> makeDeepCopyInteger(ArrayList<Integer> old){ 
    ArrayList<Integer> copy = new ArrayList<Integer>(old.size()); 
    for(Integer i : old){ 
     copy.add(new Integer(i)); 
    } 
    return copy; 
} 

Sie können testen, ob dies funktioniert, indem wie etwas zu tun:

public static void main (String[] args) throws java.lang.Exception 
{ 
    ArrayList<Integer> arr = new ArrayList<>(); 
    for(int i = 0; i<5; i++){ 
     arr.add(new Integer(i)); 
    } 
    ArrayList<Integer> x = makeDeepCopyInteger(arr); 
    for(int i = 0; i<x.size(); i++){ 
     if(arr.get(i) == x.get(i)){ 
      System.out.println("Same object"); 
     } else { 
      System.out.println("Not the same object"); 
     } 
    } 
} 

Tests

Integer a = new Integer(1); 
Integer b = new Integer(a); 

System.out.println(a==b); // true 
System.out.println(System.identityHashCode(a) == (System.identityHashCode(b))); // false; 


Integer a = new Integer(1); 
Integer b = a; 

System.out.println(a==b); // true 
System.out.println(System.identityHashCode(a) == (System.identityHashCode(b))); // true 

Also aus meiner Prüfung scheint es, dass eine neue Referenz für das Kopieren zu erstellen zu einem neuen Array sollten Sie verwenden. Integer ist ein unveränderliches Objekt, aber diese Referenz ändert sich, wenn sich der Wert Integer ändert.

+2

Da "Integer" unveränderlich ist, brauchen Sie * keine Kopie davon zu erstellen. – Kayaman

+0

@Kayaman Ich habe etwas getestet, siehe meine Bearbeitung. Vielleicht bin ich verwirrt, aber indem ich keine Kopie erstelle, scheint es die alte Referenz zu behalten. – px06

+0

Es ist nichts falsch daran. Da sich der Wert von "Integer" nicht ändern kann, spielt es keine Rolle, ob Sie beispielsweise 1000 Listen haben, die sich alle auf dieselbe "17" beziehen. Dein letzter Absatz ist falsch. Da "Ganzzahl" unveränderlich ist, kann sich ihr Wert nicht ändern. – Kayaman

1

Streams verwenden, um Objekte zu kopieren. Einfach zu lesen, gut für JIT. Der folgende Code enthält eine Kopie einer Liste mit Integer-Objektkopien.

private ArrayList<Integer> makeDeepCopyInteger(ArrayList<Integer> a){ 
    return a.stream().map(val -> new Integer(val)).collect(toList()); 
} 

kopieren benutzerdefinierte als Integer Überschreibung andere Objekte implementieren und rufen Klon()

return a.stream().map(MyObjectClass::clone).collect(toList()); 

Statt Klon Sie Serialisierung json verwenden können. Z.B. wie in den folgenden java-utils

+1

Willkommen beim Stapelüberlauf :-) Bitte schauen Sie auf [antwort]. Sie sollten einige Informationen angeben, warum Ihr Code das Problem löst. Code-only-Antworten sind für die Community nicht nützlich. – JimHawkins

0

Sie in BeanUtils.getCopy (sourceBean) verwendet tun könnte so etwas wie:

public static List<Integer> clone(List<Integer> source) { 
    return source.stream() 
     .map(intObj -> new Integer(intObj.intValue())) 
     .collect(Collectors.toList()); 
} 

Oder altmodischer:

public static List<Integer> clone(List<Integer> source) { 
    List<Integer> newList = new ArrayList<>(); 
    for(Integer intObj : source) { 
     newList.add(new Integer(intObj.intValue())); 
    } 
    return newList; 
} 

beider könnte kürzer gemacht, indem Auto-Boxing/Auto-Unboxing genutzt wird. Aber ich habe es explizit gemacht, um absolut klar zu machen, was vor sich geht.

Es ist jedoch eine sinnlose Übung - in der Tat ist es aktiv speicherverschwendend und leistungsschädlich. Integer ist unveränderlich, so ist es besser für Referenzen auf die gleiche Instanz von Integer zeigen. Da der Wert Integer nicht geändert werden kann, ist es unmöglich, durch die gemeinsame Nutzung einer Instanz Schaden zu verursachen.

Dies gilt für unveränderliche Objekte im Allgemeinen und ist der Grund, dass sie eine gute Sache sind.

Sie sind sehr unwahrscheinlich, als Anfänger, einen Fall zu finden, in dem new Integer(...) eine gute Idee ist (oder sogar Integer.valueOf(int i), obwohl diese eine zwischengespeicherte Instanz zurückgeben könnte). Wenn Sie bereits ein Integer haben, verwenden Sie den Sie haben:

Integer oldVar = ... ; 
Integer newVar = oldVar; 

Unveränderlichkeit bedeutet, dass immer in Ordnung sein wird. Es ist unmöglich, dass eine Operation newVaroldVar beschädigt, weil es keine newVar.setValue(newValue) gibt.

Wenn Sie ein int es direkt verwenden und erlauben Java Auto-Boxen in ein Integer zu konvertieren:

int oldValue = ... ; 
Integer newValue = oldValue ; // Java will automatically put this through 
           // Integer.valueOf(int i) 

Sie haben erwähnt, dass Sie wirklich mit booleans arbeiten wollte. Sie sollten in Betracht ziehen, BitSet zu verwenden.

Verwandte Themen