我正在尝试创建一种方法来深复制我的链接列表。在我的get(index)方法中,我正在创建一个新的Node。仍然没有用,但是正在通过参考。
SLinkedList<E> newLinkedList=new SLinkedList<E>();
for(int i=0;i<size();i++)
{
newLinkedList.addLast(get(i));
}
return newLinkedList;
}
答案 0 :(得分:0)
每个E类型的实例都需要深度复制
深层复制,意味着取消对字段的引用:不是对要复制的对象进行引用,而是为任何引用的对象创建新的复制对象,并将这些引用放置在副本中。结果与浅表副本给出的结果不同,副本副本所引用的对象与原点引用的对象不同,并且是独立的。
您可以执行以下操作之一:
广告2)
// example class
class E {
// exampe field
private B someField;
// copy constructor
public E(E origin) {
// deep copy item field here
somefield = origin != null
? new B(origin.someField)
: null;
}
}
ad 1)覆盖并实现克隆方法
/**
* Creates and returns a copy of this object. The precise meaning
* of "copy" may depend on the class of the object. The general
* intent is that, for any object {@code x}, the expression:
* <blockquote>
* <pre>
* x.clone() != x</pre></blockquote>
* will be true, and that the expression:
* <blockquote>
* <pre>
* x.clone().getClass() == x.getClass()</pre></blockquote>
* will be {@code true}, but these are not absolute requirements.
* While it is typically the case that:
* <blockquote>
* <pre>
* x.clone().equals(x)</pre></blockquote>
* will be {@code true}, this is not an absolute requirement.
* <p>
* By convention, the returned object should be obtained by calling
* {@code super.clone}. If a class and all of its superclasses (except
* {@code Object}) obey this convention, it will be the case that
* {@code x.clone().getClass() == x.getClass()}.
* <p>
* By convention, the object returned by this method should be independent
* of this object (which is being cloned). To achieve this independence,
* it may be necessary to modify one or more fields of the object returned
* by {@code super.clone} before returning it. Typically, this means
* copying any mutable objects that comprise the internal "deep structure"
* of the object being cloned and replacing the references to these
* objects with references to the copies. If a class contains only
* primitive fields or references to immutable objects, then it is usually
* the case that no fields in the object returned by {@code super.clone}
* need to be modified.
* <p>
* The method {@code clone} for class {@code Object} performs a
* specific cloning operation. First, if the class of this object does
* not implement the interface {@code Cloneable}, then a
* {@code CloneNotSupportedException} is thrown. Note that all arrays
* are considered to implement the interface {@code Cloneable} and that
* the return type of the {@code clone} method of an array type {@code T[]}
* is {@code T[]} where T is any reference or primitive type.
* Otherwise, this method creates a new instance of the class of this
* object and initializes all its fields with exactly the contents of
* the corresponding fields of this object, as if by assignment; the
* contents of the fields are not themselves cloned. Thus, this method
* performs a "shallow copy" of this object, not a "deep copy" operation.
* <p>
* The class {@code Object} does not itself implement the interface
* {@code Cloneable}, so calling the {@code clone} method on an object
* whose class is {@code Object} will result in throwing an
* exception at run time.
*
* @return a clone of this instance.
* @throws CloneNotSupportedException if the object's class does not
* support the {@code Cloneable} interface. Subclasses
* that override the {@code clone} method can also
* throw this exception to indicate that an instance cannot
* be cloned.
* @see Cloneable
*/
@Override
protected Object clone() throws CloneNotSupportedException {
return super.clone();
}
我认为没有办法强制使用泛型使用复制构造函数。可克隆是这里唯一的选择-@Ivan
所有OP的冷杉都没有提到E是否为通用类型 但是...如果是这样的话?
interface Copyable<T> {
T copy();
}
final class Wrapped <E extends Copyable<E>> {
private E theObject;
public Wrapped(E arg) { theObject = arg.copy(); }
public void setObject(E arg) { theObject = arg.copy(); }
public E getObject() { return theObject.copy(); }
public boolean equals(Object other) {
if (other == null) return false;
if (! (other instanceof Wrapped)) return false;
return (this.theObject.equals(((Wrapped)other).theObject));
}
}
GENERICS HOW TO COPY –如何最好地实现泛型类型的clone方法?
请记住,最好使用克隆方法来构造副本:)
因此,在REFLECTION的帮助下,我们可以执行以下操作:
public static <E> E createCopy(E item) throws UnsupportedOperationException {
try {
Class<?> clazz = item.getClass();
Constructor<?> copyConstructor = clazz.getConstructor(clazz);
@SuppressWarnings("unchecked")
E copy = (E) copyConstructor.newInstance(item);
return copy;
} catch (Exception e) {
throw new UnsupportedOperationException(e.getCause());
}
}
编辑:我最终以递归的方式进行了工作,并且有效。 C流
也许JAVA更少混乱(不是通用解决方案,但是当您知道E是具有深度克隆方法的具体类型时)?
java.util.LinkedList<DeepCloneable> origin;
java.util.LinkedList<DeepCloneable> copy = origin != null
? new java.util.LinkedList<>(origin.size())
: null;
java.util.Iterator<DeepCloneable> iterator = origin != null
? origin.iterator()
: null;
while (iterator != null
&& iterator.hasNext()) {
DeepCloneable next = iterator.next();
DeepCloneable dcCopy = next.deepClone();
copy.add(dcCopy);
}
答案 1 :(得分:0)
要进行深复制,您需要知道如何复制E
。
由于您不知道E
是什么,因此需要告知您如何复制E
,例如通过接受UnaryOperator<E>
进行复制操作。
以下内容将显示使用标准LinkedList
的方法示例,但是它很容易适应您的自定义实现。
public static <E> LinkedList<E> deepCopy(LinkedList<E> original, UnaryOperator<E> copyOperator) {
LinkedList<E> newList = new LinkedList<>();
for (E e : original)
newList.add(copyOperator.apply(e));
return newList;
}
对象可复制的一种常见方式是实现Cloneable
:
class CloneableObject implements Cloneable {
private String value;
public CloneableObject(String value) {
this.value = value;
}
@Override
public CloneableObject clone() {
try {
return (CloneableObject) super.clone();
} catch (CloneNotSupportedException e) {
throw new AssertionError(e.toString(), e); // cannot happen
}
}
public String getValue() {
return this.value;
}
public void setValue(String value) {
this.value = value;
}
}
LinkedList<CloneableObject> cloneableList = /*...*/;
LinkedList<CloneableObject> cloneableCopy = deepCopy(cloneableList, CloneableObject::clone);
另一种普遍接受的方法是使对象实现一个复制构造函数:
class CopyableObject {
private String value;
public CopyableObject(String value) {
this.value = value;
}
public CopyableObject(CopyableObject original) { // copy constructor
this.value = original.value;
}
public String getValue() {
return this.value;
}
public void setValue(String value) {
this.value = value;
}
}
LinkedList<CopyableObject> copyableList = /*...*/;
LinkedList<CopyableObject> copyableCopy = deepCopy(copyableList, CopyableObject::new);
当然,如果该类未实现自我复制的方法,则始终可以自己进行:
class SimpleObject {
private String value;
public String getValue() {
return this.value;
}
public void setValue(String value) {
this.value = value;
}
}
LinkedList<SimpleObject> simpleList = /*...*/;
LinkedList<SimpleObject> simpleCopy = deepCopy(simpleList, o -> {
SimpleObject copy = new SimpleObject();
copy.setValue(o.getValue());
return copy;
});
答案 2 :(得分:-1)
我最终以递归的方式进行了工作,并且成功了。
SLinkedList<E> newLinkedList=new SLinkedList<E>();
SNode<E> cur=head;
if(cur==null) {
return newLinkedList;
}
while(cur!=null) {
newLinkedList.addLast(cur.element.deepClone());
cur=cur.next;
}
return newLinkedList;
}