[英]Ovewriting toString method in deque class using generics
我正在尝试使用toString
方法在双端队列中打印第一个和最后一个元素,但是我不确定我是否正确覆盖了toString
方法。
据我所知,所有方法似乎都正常运行,但是由于看不到任何可读的输出,所以我无法分辨。
我知道已经有一个双端队列接口,但这是在Java中使用泛型的练习的一部分。
这段代码应该创建一个双端队列,能够将值添加到双端队列的前面,可以从前面删除值,可以在后面添加值,也可以从后面删除值。
这是有问题的课程:
import java.util.Iterator;
import java.util.NoSuchElementException;
class Deque<T> implements Iterable<T> {
private class Node<T> {
public Node<T> left, right;
private final T item;
public Node(T item) {
if (item == null) {
throw new NullPointerException();
}
this.item = item;
}
public void connectRight(Node<T> other) {
this.right = other;
other.left = this;
}
}
private class DequeIterator implements Iterator<T> {
private Node<T> curr = head;
public boolean hasNext() {
return curr != null;
}
public void remove() {
throw new UnsupportedOperationException();
}
public T next() {
if (!hasNext()) {
throw new NoSuchElementException();
}
T item = curr.item;
curr = curr.right;
return item;
}
}
private Node<T> head, tail;
private int size;
public Iterator<T> iterator() {
return new DequeIterator();
}
public Deque() {
}
public int size() {
return size;
}
public boolean isEmpty() {
return size() == 0;
}
public void checkInvariants() {
assert size >= 0;
assert size > 0 || (head == null && tail == null);
assert (head == null && tail == null) || (head != null && tail != null);
}
public void addFirst(T item) {
Node<T> prevHead = head;
Node<T> newHead = new Node<T>(item);
if (prevHead != null) {
newHead.connectRight(prevHead);
} else {
tail = newHead;
}
head = newHead;
size++;
checkInvariants();
}
public void addLast(T item) {
Node<T> newTail = new Node<T>(item);
Node<T> prevTail = tail;
if (prevTail != null) {
prevTail.connectRight(newTail);
} else {
head = newTail;
}
tail = newTail;
size++;
checkInvariants();
}
public T removeFirst() {
if (isEmpty()) {
throw new java.util.NoSuchElementException();
}
size--;
Node<T> prevHead = head;
head = prevHead.right;
prevHead.right = null;
if (head != null) {
head.left = null;
}
checkInvariants();
return prevHead.item;
}
public T removeLast() {
if (isEmpty()) {
throw new java.util.NoSuchElementException();
}
size--;
Node<T> prevTail = tail;
tail = prevTail.left;
prevTail.left = null;
if (tail != null) tail.right = null;
checkInvariants();
return prevTail.item;
}
@Override
public String toString() {
Node<T> currTail = tail;
Node<T> currHead = head;
head = currHead.right;
tail = currTail.left;
StringBuilder builder = new StringBuilder();
while (currHead != null && currTail != null) {
builder.append(currHead.item + "\n");
}
return builder.toString();
}
public static void main(String[] args) {
Deque<Double> d = new Deque<Double>();
d.addFirst(1.0);
System.out.println(d);
d.addLast(1.0);
//d.removeFirst();
//d.removeLast();
System.out.println(d.toString());
}
}
首先,您将实例变量head和tail设置为它们各自的邻居,这绝对不是您要做的事情。 这会使您的队列处于不一致的状态,其中第二个元素是头部,但是它仍然具有左邻居,即原始头部。 尾巴也一样。 通常, toString
方法不应有副作用。
while循环中currTail
和currHead
都不会改变,因此如果双端队列为非空,则条件currHead != null && currTail != null
始终为true。 您必须在循环中设置这些变量,但是,您无需一次从两端进行迭代。 从头开始迭代就足够了。 然后,您可以使用for循环,如下所示:
@Override
public String toString() {
final StringJoiner stringJoiner = new StringJoiner("\n");
for (Node<T> node = head; node != null; node = node.right) {
stringJoiner.add(node.item.toString());
}
return stringJoiner.toString();
}
每次迭代后,这会将变量node
为它的右邻居,如果双端队列为空,则一开始node
将为null,并且不会按预期方式进入循环。
这只是更简洁的版本(在我看来):
@Override
public String toString() {
final StringJoiner stringJoiner = new StringJoiner("\n");
Node<?> node = head;
while (node != null) {
stringJoiner.add(node.item.toString());
node = node.right;
}
return stringJoiner.toString();
}
这基本上是您的尝试,只是固定的。
并不是说我使用了StringJoiner
而不是StringBuilder
,因为它允许您设置每个String之间使用的StringJoiner
符,而这正是您正在做的事情。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.