我有一个编程任务,用Java创建一个通用堆栈,我需要制作一个newNode T的深层副本。我不知道如何创建一个深度复制的方法可以访问它自己并输出我的深层副本。到目前为止,我有这个:
public class Stack<T>
{
private T[] data;
private int top;
private int size;
public Stack( )
{ top = -1;
size = 100;
data = (T[])new Object[100];
}
public Stack(int n)
{ top = -1;
size = n;
data = (T[])new Object[n];
}
public boolean push(T newNode)
{ if(top == size-1)
return false; // ** overflow error **
else
{ top = top +1;
data[top] = newNode.deepCopy();
return true; // push operation successful
}
}
public T pop( )
{ int topLocation;
if(top == -1)
return null; // ** underflow error **
else
{ topLocation = top;
top = top -1;
return data[topLocation];
}
}
public void showAll( )
{ for(int i = top; i >= 0; i--)
System.out.println(data[i].toString());
}
}
如何制作newNode的深层副本。我很确定我需要一个接口用于该方法,但过去我失去了。
也许最通用和最直接的解决方案是要求使用代码在构造时提供深度复制例程:
public class Stack<T> {
...
private final Function<T, T> elementCopier;
public Stack<T>(Function<T, T> elementCopier) {
// make sure thy are not passing you a null copier:
this.elementCopier = Objects.requiresNonNull(elementCopier);
...
}
...
public boolean push(T element) {
...
data[top] = elementCopier.apply(element);
...
}
...
}
因此,例如对于可克隆的类类型,其中.clone()实际上是一个deepCopy,用户代码就像:
Stack<MyElemClz> stack = new Stack<>(x -> x.clone());
// or:
Stack<MyElemClz> stack = new Stack<>(MyElemClz::clone);
...
MyElemClaz elem = ...;
...
stack.push(elem);
如果类型是一个像String这样的常量简单对象,则不需要克隆,在这种情况下,用户会将标识lambda x -> x
表示为复制器:
Stack<String> stack = new Stack<>(x -> x)
如果用户坚持制作副本,即使该类是常量,您也可以强制它:
Stack<String> stack = new Stack<>(x -> new String(x))
// or
Stack<String> stack = new Stack<>(String::new)
可以使用ObjectOutputStream/ObjectInputStream
制作深层复制品。然后,人们不会存储Object(对可更改字段的引用),而是存储堆栈中的序列化字节。
在它上面。
ObjectOutputStream执行深层复制。
如果你想使用界面,或者你不喜欢Valentin的方法,你可以这样做:
interface Copiable<T> {
T deepCopy();
}
public class Stack<T extends Copiable<T>> {
...
}
然后将deepCopy
方法实现到放在堆栈中的对象,即
class A implements Copiable<A> {
@Override
public A deepCopy() {
// ... your copy code here
}
}
Stack<A> stack = new Stack<>();
等等