繁体   English   中英

使用泛型在双端队列中写toString方法

[英]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循环中currTailcurrHead都不会改变,因此如果双端队列为非空,则条件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.

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