简体   繁体   English

将 ArrayList 元素克隆到同一个 ArrayList

[英]Clonning ArrayList element to the same ArrayList

I have an ArrayList that contains objects.我有一个包含对象的ArrayList (this objects are clases, every object contains an incredibly large amount of information, precisely these object represent large electric generators, so copying the properties one by one is not an option). (这个对象是类,每个对象都包含大量的信息,正是这些对象代表了大型发电机,因此无法逐一复制属性)。

example:例子:

ArrayList arr = {ob1, ob2, ob3, ob4, ob5}

So what I try to do is to clone the object (ob1) to the position 5.所以我尝试做的是将对象(ob1)克隆到位置 5。

arr.set(4, arr.get(0));

But somehow, doing that, ob5 is not a copy ob ob1, it is ob1, so if I change ob5, ob1 changes too.但不知何故,这样做,ob5 不是复制 ob ob1,它是 ob1,所以如果我改变 ob5,ob1 也会改变。

Is this something inherent to ArrayLists?这是 ArrayLists 固有的东西吗? Is there any difference if I use Lists instead?如果我改用 Lists 有什么区别吗?

ArrayList save the reference yes. ArrayList 保存引用是的。 But you may clone it (Attention! But it will be the shallow copy - it will not clone as well for internal objects https://stackoverflow.com/a/13434779/1111527 )但是你可以克隆它(注意!但它将是浅拷贝 - 它不会克隆内部对象https://stackoverflow.com/a/13434779/1111527

private class JustToCheck implements Cloneable {

    @Override
    public Object clone() throws CloneNotSupportedException {
        return super.clone();
    }
}

And then use like this然后像这样使用

JustToCheck ob1 = new JustToCheck();
JustToCheck ob2 = ob1;

List<JustToCheck> arr = new ArrayList<JustToCheck>();
arr.add(ob1);
arr.add(ob2);

System.out.println(arr.get(0).toString() + ": " + arr.get(1).toString());

try {
    arr.set(1, (JustToCheck) ob1.clone());
} catch (CloneNotSupportedException e) {
    e.printStackTrace();
}

System.out.println(arr.get(0).toString() + ": " + arr.get(1).toString());

Output is输出是

example$JustToCheck@1c39a2d: example$JustToCheck@1c39a2d
example$JustToCheck@1c39a2d: example$JustToCheck@bf2d5e


PS - I have checked the issue in answers https://stackoverflow.com/a/13434813/1111527 PS - 我已经检查了答案https://stackoverflow.com/a/13434813/1111527 中的问题

there something with immutable classes有一些不可变的类

Java6 Java6

String a = new String("a");
String b = a;
b += "b"; 
System.out.println("a = " + a); // a = a
System.out.println("b = " + b); // b = ab

This is because you are doing a shadow copy instead of a deep copy.这是因为您正在执行卷影复制而不是深层复制。

Shallow copy : If a shallow copy is performed on Obj-1 then it is copied but its contained objects are not.浅拷贝:如果在Obj-1上执行浅拷贝,则复制它但不复制其包含的对象。 The contained objects Obj-1 and Obj-2 are affected by changes to cloned Obj-2 .包含的对象Obj-1Obj-2受克隆 Obj-2 更改的影响 Java supports shallow cloning of objects by default when a class implements the java.lang.Cloneable interface.当类实现 java.lang.Cloneable 接口时,Java 默认支持对象的浅层克隆。

Deep copy : If a deep copy is performed on obj-1 as shown then not only obj- 1 has been copied but the objects contained within it have been copied as well .深副本:如果一个深拷贝是在执行obj-1所示,那么不仅obj- 1已经被复制,但对象包含在它已被复制为好 Serialization can be used to achieve deep cloning.序列化可用于实现深度克隆。 Deep cloning through serialization is faster to develop and easier to maintain but carries a performance overhead.通过序列化进行深度克隆的开发速度更快且更易于维护,但会带来性能开销。 source 来源

An example of Deep Copy:深拷贝的一个例子:

class Student implements Cloneable {
  //Contained object
  private Subject subj;
  private String name;

  public Subject getSubj() {..}
  public String getName() {..}

  public Object clone() {
    //Deep copy
    Student s = new Student(name, subj.getName());
    return s;
  }
}

This will be true anywhere in Java.在 Java 中的任何地方都是如此。 Nothing will get copied unless you do so explicitly.除非您明确这样做,否则不会复制任何内容。 (Indeed, there are objects which it is deliberately impossible to copy.) (确实,有些对象是故意无法复制的。)

You need to make a copy of your ElectricGenerator .您需要制作ElectricGenerator的副本。 The most common options are introducing a copy constructor or implementing the clone method.最常见的选项是引入复制构造函数或实现克隆方法。 Both of those solutions however require to copy all those properties.然而,这两种解决方案都需要复制所有这些属性。

Once you have that, you can do一旦你有了它,你就可以做到

//copy constructor
arr.add( new ElectricGenerator( arr.get( 0 ) ) );
//clone
arr.add( arr.get( 0 ).clone() );

An alternative is to serialize/deserialize the object另一种方法是序列化/反序列化对象

This is not adherent to ArrayList, this is a java feature.这不符合 ArrayList,这是一个 java 特性。 New object is not created, only a reference is passed.不创建新对象,只传递一个引用。 The ArrayList thus stores two references.因此 ArrayList 存储了两个引用。 You have to use .clone() method of your object.您必须使用对象的 .clone() 方法。

arr.set(4, arr.get(0).clone());

This will create new copy of the object, even though this copy will be shallow.这将创建对象的新副本,即使此副本将是浅的。 You have to override the clone method to make it a deep copy if needed.如果需要,您必须覆盖 clone 方法以使其成为深层副本。

No it is because in Java you create references to the objects so even if you don't use ArrayList and do something like this:不,这是因为在 Java 中,您创建了对对象的引用,因此即使您不使用 ArrayList 并执行以下操作:

String a = new String("a");
String b = a;

b += "b";

both a and b are equal "ab". a 和 b 都等于“ab”。

(the exeption from this are basic types like int (but not instances of Integer there are different things)). (例外是像 int 这样的基本类型(但不是 Integer 的实例,有不同的东西))。

So the answer to your question is here : How to copy an object by value, not by reference and here : http://www.itcsolutions.eu/2010/12/29/tutorial-java-6-4-2-how-to-copy-values-of-an-array-into-another-array/所以你的问题的答案在这里: 如何通过值复制对象,而不是通过引用和这里: http : //www.itcsolutions.eu/2010/12/29/tutorial-java-6-4-2-how -to-copy-values-of-an-array-into-another-array/

The list only contains the pointer to the objects..该列表仅包含指向对象的指针..

If you move the ob1 to the ob5 what happens it that you tell the list to put the pointer to the ob1 where the pointer of the ob5 was, therefore losing your pointer to ob5 and duplicating the pointer to ob1...如果您将 ob1 移动到 ob5 会发生什么,您告诉列表将指针指向 ob5 的指针所在的 ob1,因此丢失指向 ob5 的指针并复制指向 ob1 的指针...

You will need to create an other object that contains a duplication of the values and then assign this object to the position 4您将需要创建一个包含重复值的其他对象,然后将此对象分配给位置 4

Object variables are different from primitive data types.对象变量不同于原始数据类型。

int x = 2;
int y = x;

x and y refer to different memory locations. x 和 y 指的是不同的内存位置。

MyClass x = new MyClass();
MyClass y = x;

x and y refer to the same memory location, but that location has two references. x 和 y 引用相同的内存位置,但该位置有两个引用。 Any change made to one will change the other.对其中一个所做的任何更改都会改变另一个。 On way to fix this is to implement Cloneable and use the .clone() method.解决这个问题的方法是实现Cloneable并使用.clone()方法。

shallow copying creates a new instance of the same class and copies all the fields to the new instance and returns it. shallow copying创建同一个类的新实例,并将所有字段复制到新实例并返回它。 Object class provides a clone method and provides support for the shallow copying. Object 类提供了一个 clone 方法,并提供了对浅拷贝的支持。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM