我正在尝试学习数据结构,但我遇到了可怕的NullPointerException
,我不知道如何修复它。
我的SinglyLinkedList<E>
类实现了一个界面LinkedList
,我重新定义了一些方法,例如add(), get(), contains()
等。
使用NullPointerException
方法时会发生clear()
。它指向removeLast()
下的方法nodeBefore.setNext(null)
。它还指向clear()
下的remove(head.getElement())
方法。
此外,如果我的代码中有任何可以改进的内容,请告诉我。
public class SinglyLinkedList<E> implements LinkedList<E> {
private class Node<E> {
public Node<E> next;
public E element;
public Node(E element) {
this.element = element;
}
public Node (E element, Node<E> next) {
this.element = element;
this.next = next;
}
public E getElement() {
return element;
}
public Node<E> getNext() {
return next;
}
public void setElement(E element) {
this.element = element;
}
public void setNext(Node<E> next) {
this.next = next;
}
public String toString() {
return ("[" + element + "] ");
}
}
public Node<E> head;
public Node<E> tail;
public int total;
public SinglyLinkedList() {
this.head = null;
this.tail = null;
this.total = 0;
}
public E get(int index) {
if (index < 0 || index > size()) {
return null;
}
if (index == 0) {
return head.getElement();
}
Node<E> singly = head.getNext();
for (int i = 1; i < index; i ++) {
if (singly.getNext() == null) {
return null;
}
singly = singly.getNext();
}
System.out.println("\n" + singly.getElement());
return singly.getElement();
}
public void add(E element) {
Node<E> singlyAdd = new Node<E>(element);
if (tail == null) {
head = singlyAdd;
tail = singlyAdd;
} else {
tail.setNext(singlyAdd);
tail = singlyAdd;
}
total++;
}
public void display() {
if (head == null) {
System.out.println("empty list");
} else {
Node<E> current = head;
while (current != null) {
System.out.print(current.toString());
current = current.getNext();
}
}
}
public boolean contains(E data) {
if (head == null) {
return false;
}
if (head.getElement() == data) {
System.out.println(head);
return true;
}
while (head.getNext() != null) {
head = head.getNext();
if (head.getElement() == data) {
System.out.println(head);
return true;
}
}
return false;
}
private Node<E> removeFirst() {
if (head == null) {
System.out.println("We cant delete an empty list");
}
Node<E> singly = head;
head = head.getNext();
singly.setNext(null);
total--;
return singly;
}
private Node<E> removeLast() {
Node<E> nodeBefore;
Node<E> nodeToRemove;
if (size() == 0) {
System.out.println("Empty list");
}
nodeBefore = head;
for (int i = 0; i < size() - 2; i++) {
nodeBefore = nodeBefore.getNext();
}
nodeToRemove = tail;
nodeBefore.setNext(null);
tail = nodeBefore;
total--;
return nodeToRemove;
}
public E remove(int index) {
E hold = get(index);
if (index < 0 || index >= size()) {
return null;
} else if (index == 0) {
removeFirst();
return hold;
} else {
Node<E> current = head;
for (int i = 1; i < index; i++) {
current = current.getNext();
}
current.setNext(current.getNext().getNext());
total--;
return hold;
}
}
public int size() {
return getTotal();
}
public boolean remove(E data) {
Node<E> nodeBefore, currentNode;
if (size() == 0) {
System.out.println("Empty list");
}
currentNode = head;
if (currentNode.getElement() == data) {
removeFirst();
}
currentNode = tail;
if (currentNode.getElement() == data) {
removeLast();
}
if (size() - 2 > 0) {
nodeBefore = head;
currentNode = head.getNext();
for (int i = 0; i < size() - 2; i++) {
if (currentNode.getElement() == data) {
nodeBefore.setNext(currentNode.getNext());
total--;
break;
}
nodeBefore = currentNode;
currentNode = currentNode.getNext();
}
}
return true;
}
public void clear() {
while (head.getNext() != null) {
remove(head.getElement());
}
remove(head.getElement());
}
private int getTotal() {
return total;
}
}
答案 0 :(得分:2)
对于clear
方法,我没有看到您对每个元素清理做了任何操作,返回类型为void
,因此您只需要一个空列表。最简单的方法是简单地清除所有内容,例如在构造函数中:
public void clear() {
this.head = null;
this.tail = null;
this.total = 0;
}
另一条评论:
在contains
,
while (head.getNext() != null) {
head = head.getNext();
if (head.getElement() == data) {
System.out.println(head);
return true;
}
}
可能有两个问题(第一个适用于整个班级),
== data
进行比较,您可能希望将值与.equals(data)
进行比较 编辑:即。 n.getElement().equals(data)
代替n.getElement() == data
。
(或者,如果n
和data
可能是null
,则(data != null ? data.equals(n.getElement()) : data == n.getElement())
head
作为修改列表状态的扫描变量。你真的想要吗?答案 1 :(得分:2)
当您删除clear
中的最后一个元素时出现问题:remove(head.getElement());
。出于某种原因,您首先删除head
,然后删除tail
。但是在致电removeLast
时,您使用head
(已经是null
)。在removeLast
内,这就是该行,这会导致NullPointerException
:nodeBefore.setNext(null);
。
我的建议是编写@ {bali182建议的clear()
方法:
public void clear() {
this.head = null;
this.tail = head;
this.total = 0;
}
一个建议:如果您正在编写搜索或删除条目的方法,则在处理对象时不应使用==
(甚至更好:在处理对象时根本不使用==
)。您可能需要阅读this thread。
答案 2 :(得分:0)
在clear方法中,您正在调用remove(head.getElement());
,这意味着您正在尝试调用LinkedList的删除方法。并且由于您要覆盖每个功能,因此添加,您不会维护LinkedList的内部状态,因此您将获得异常。删除的代码是:
public boolean remove(Object o) {
if (o==null) {
for (Entry<E> e = header.next; e != header; e = e.next) {
if (e.element==null) {
因此,由于您没有使用LinkedList的功能,因此标头将为null并且执行header.next
将返回NullPointerException。