リンクリストの実装でtraverse()メソッドを実行しているときにスタックオーバーフローエラーが発生する理由を100%確信していません。私がtraverse()メソッドをコメントアウトすると、プログラムは正常に動作します。リンクリストを反復する際のスタックオーバーフローエラー
サイズ変数を使用して反復処理を行い、トラバースメソッド内でカウンタ変数を作成することによって2回確認されましたが、スタックオーバーフローエラーが発生します。
@Override
public void traverse() {
Node<T> data = this.head; // In order traversal
int counter = 0;
while (counter < size) {
System.out.println(data.toString());
data = data.getNextNode();
counter++;
}
}
リンクリストクラス
public class LinkedList<T extends Comparable<T>> implements List<T> {
private Node<T> head; // First element of linked list
private Node<T> tail; // Last element of linked list
private int size;
public LinkedList() {
this.size = 0;
}
/**
* TODO: Implement iterator and ForEach methods later on
* */
@Override
public Iterator<T> iterator() {
return null;
}
@Override
public void forEach(Consumer<? super T> action) {
}
@Override
public Spliterator<T> spliterator() {
return null;
}
private class Node<T> {
private T data;
private Node<T> prevNode;
private Node<T> nextNode;
public Node(T data) {
this.data = data;
}
public Node(T data, Node<T> nextNode, Node<T> prevNode) {
this.data = data;
this.nextNode = nextNode;
this.prevNode = prevNode;
}
public T getData() {
return data;
}
public void setData(T data) {
this.data = data;
}
public Node<T> getPrevNode() {
return prevNode;
}
public void setPrevNode(Node<T> prevNode) {
this.prevNode = prevNode;
}
public Node<T> getNextNode() {
return nextNode;
}
public void setNextNode(Node<T> nextNode) {
this.nextNode = nextNode;
}
@Override
public String toString() {
return "Node{" +
"data=" + data +
", prevNode=" + prevNode +
", nextNode=" + nextNode +
'}';
}
}
/**
* Add element to the start of the linked list
* */
@Override
public void add(T data) {
// head is the first element. If inserted at the front of this list, this will constantly change
Node<T> node = new Node<>(data, this.head, null);
if (this.head != null) {
this.head.setPrevNode(node);
}
// Temporarily set new data as the head
this.head = node;
if (this.tail == null) {
this.tail = node; // If tail is not set, make newly inserted node as tail;
}
incrementSize();
}
@Override
public void remove(T data) {
// TODO
decrementSize();
}
@Override
public void removeFirst() {
// TODO
decrementSize();
}
@Override
public void traverse() {
Node<T> data = this.head; // In order traversal
while (data != null) {
System.out.println(data.toString());
data = data.getNextNode();
}
}
@Override
public int size() {
return this.size;
}
/**
* ===================================
* Private methods here
* */
private void decrementSize() {
this.size--;
}
private void incrementSize() {
this.size++;
}
}
Listインタフェース
public interface List<T> extends Iterable<T> {
void add(T data);
void remove(T data);
void removeFirst();
void traverse();
int size();
}
Mainメソッド以下
public class App {
public static void main(String[] args) {
List<Integer> linkedList = new LinkedList<>();
linkedList.add(10);
linkedList.add(20);
linkedList.add(30);
linkedList.traverse(); // Error here
System.out.println(linkedList.size());
}
}
は、スタックトレース
ですException in thread "main" java.lang.StackOverflowError
at java.lang.AbstractStringBuilder.append(AbstractStringBuilder.java:449)
at java.lang.StringBuilder.append(StringBuilder.java:136)
at linkedlist.practice.LinkedList$Node.toString(LinkedList.java:79)
at java.lang.String.valueOf(String.java:2994)
at java.lang.StringBuilder.append(StringBuilder.java:131)
at linkedlist.practice.LinkedList$Node.toString(LinkedList.java:79)
at java.lang.String.valueOf(String.java:2994)
at java.lang.StringBuilder.append(StringBuilder.java:131)
at linkedlist.practice.LinkedList$Node.toString(LinkedList.java:79)
at java.lang.String.valueOf(String.java:2994)
at java.lang.StringBuilder.append(StringBuilder.java:131)
at linkedlist.practice.LinkedList$Node.toString(LinkedList.java:79)
at java.lang.String.valueOf(String.java:2994)
ありがとうございました。私はtoString()メソッドの再帰呼び出しを発見した後、Node内部クラスのtoString()メソッドを次のように書き直しました。 私は疑問に思っています:toString()のnullチェックは悪い考えですか?余分な作業が含まれているので、繰り返し呼び出すのは少し高価です。
@Override
public String toString() {
StringBuilder sb = new StringBuilder();
sb.append("Node{ data=");
sb.append(data);
if (prevNode != null) {
sb.append(", prevNode=").append(prevNode.getData());
}
if (nextNode != null) {
sb.append(", nextNode=").append(nextNode.getData());
}
sb.append('}');
return sb.toString();
}
ログコンソール
Node{ data=30, nextNode=20}
Node{ data=20, prevNode=30, nextNode=10}
Node{ data=10, prevNode=20}
例外のスタックトレースを投稿してください。 – khelwood
私はスタックトレースを追加しました。 –
注(何も答えが見つからないため):スタックトレースは、LinkedList.javaの79行目で 'toString'の呼び出しを繰り返し表示しています。これは問題を見つけるためのヒントです。 –