Java 为什么我的定制LinkedList不起作用?

Java 为什么我的定制LinkedList不起作用?,java,data-structures,collections,linked-list,nodes,Java,Data Structures,Collections,Linked List,Nodes,我正在尝试创建定制的LinkedList,以便更好地理解数据结构。我不知道我的LinkedList类有什么问题 package numberlist.primitivelist.objectlist; public class ObjectLinkedList extends ObjectList implements Copiable { Node firstNode; /** * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ * *

我正在尝试创建定制的LinkedList,以便更好地理解数据结构。我不知道我的LinkedList类有什么问题

package numberlist.primitivelist.objectlist;

public class ObjectLinkedList extends ObjectList implements Copiable {

Node firstNode;

/**
 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 *
 * Method: ObjectLinkedList() description:constructor
 *
 * @author Jinyu Wu Date: 2017/2/4
 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 */
public ObjectLinkedList() {
    firstNode = null;
}

/**
 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 *
 * Method: add() description: Insert an item into the list
 *
 * @param index position of the list
 * @param obj the element is going to be inserted
 * @author Jinyu Wu Date: 2017/2/4
 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 */
@Override
public void add(int index, Object obj) {
    Node tempNode = firstNode;
    Node currentNode = new Node(obj);
    if (index == 0) {
        firstNode = currentNode;
        return;
    }
    if (index < 0 || index > size()) {
        System.out.println("add(ObjectLinkedList) index out of bound exception");
    } else {
        for (int i = 1; i <= index; i++) {
            tempNode = tempNode.getNext();
            if (i == index - 1) {
                if (index != size() - 1) {
                    currentNode.setNext(tempNode.getNext());
                } else {
                    currentNode.setNext(null);
                }
                tempNode.setNext(currentNode);
            }
        }
    }

}

/**
 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 *
 * Method: removeAt() description: remove an item from a position of the
 * list
 *
 * @param index position in the list
 * @author Jinyu Wu Date: 2017/2/4
 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 */
@Override
public void removeAt(int index) {
    if (index < 0 || index > size()) {
        System.out.println("removeAt(ObjectLinkedList) index out of bound exception");
    } else {
        Node tempNode = firstNode;
        if (index == 0) {
            firstNode = firstNode.getNext();
        } else {
            for (int i = 1; i <= index; i++) {
                tempNode = tempNode.getNext();
                if (i == index - 1) {
                    if (index != size() - 1) {
                        tempNode.setNext(tempNode.getNext().getNext());
                    } else {
                        tempNode.setNext(null);
                    }
                }
            }
        }
    }

}

/**
 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 *
 * Method: remove() description: remove a specific item from a position of
 * the list
 *
 * @param obj target object is going to be removed
 * @author Jinyu Wu Date: 2017/2/4
 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 */
@Override
public void remove(Object obj) {
    if (size() > 0) {
        Node tempNode = firstNode;
        for (int i = 0; i <= size(); i++) {
            if (tempNode.equals(obj)) {
                tempNode.setNext(tempNode.getNext().getNext());
                break;
            }
            if (i < size() - 1) {
                tempNode = tempNode.getNext();
            }
        }

        System.out.println("target object is not found inside the linkedList(remove)");
    }
}

/**
 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 *
 * Method: get() description:get an item from the list
 *
 * @param index position in the list
 * @author Jinyu Wu Date: 2017/2/4
 * @return double ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 */
@Override
public Object get(int index) {
    if (index < 0 || index > size()) {
        System.out.println("get(ObjectLinkedList) index out of bound exception");
        return null;
    } else if (index == 0) {
        return firstNode;
    } else {
        Node tempNode = firstNode;
        for (int i = 0; i <= index; i++) {
            if (i == index - 1) {
                tempNode = tempNode.getNext();
                return tempNode;
            }
        }
        System.out.println("objectLinkedList get method nothing found");
        return null;
    }

}

/**
 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 *
 * Method: toString() description: print out the content of the list
 *
 * @author Jinyu Wu Date: 2017/2/4
 * @return Integer ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 */
@Override
public String toString() {
    return "ObjectLinkedList{" + "firstNode=" + firstNode + '}';
}

/**
 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 *
 * Method: find() description:get an item from the list
 *
 * @author Jinyu Wu Date: 2017/2/4
 * @param obj Object is going to be found
 * @return Integer ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 */
@Override
public int find(Object obj) {
    Node tempNode = firstNode;
    Node newNode = new Node(obj);
    if (newNode.equals(firstNode)) {
        return 0;
    } else {
        for (int i = 1; i < size(); i++) {
            if (tempNode.equals(newNode)) {
                return i;
            }
            tempNode = tempNode.getNext();
        }
        return -1;
    }

}

/**
 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 *
 * Method: size() description:get the size of the list
 *
 * @author Jinyu Wu Date: 2017/2/4
 * @return Integer ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 */
@Override
public int size() {
    int size = 1;
    if (firstNode == null) {
        return 0;
    }
    try {
        for (Node n = firstNode; n.getNext() != null; n = n.getNext()) {
            size++;
        }
        return size;
    } catch (NullPointerException e) {
        return size;
    }
}

/**
 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 *
 * Method: deepCopy() description: make a deepCoy for this object
 *
 * @author Jinyu Wu Date: 2017/2/4
 * @return String ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 */
@Override
public ObjectLinkedList deepCopy() {
    ObjectLinkedList newList = new ObjectLinkedList();
    Node currentNode = firstNode;

    for (int i = 0; i < size(); i++) {
        Node newNode = new Node(currentNode.getValue());
        newList.add(i, newNode);
        currentNode = currentNode.getNext();
    }

    return newList;

}
}

以下是我得到的错误:

我的节点类:

package numberlist.primitivelist.objectlist;

public class Node {

private Node nextNode;
private Object obj;

/**
 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 *
 * Method: Node() description: constructor
 *
 * @author Jinyu Wu Date: 2017/2/4
 * @param obj set the value
 */
public Node(Object obj) {
    this.obj = obj;
    this.nextNode = null;
}

/**
 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 *
 * Method: getValue() description: get the value of object
 *
 * @author Jinyu Wu Date: 2017/2/4
 * @return return the object
 */
public Object getValue() {
    return this.obj;
}

/**
 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 *
 * Method: setValue() description: setValue for the Node
 *
 * @author Jinyu Wu Date: 2017/2/4
 * @param obj return the value
 */
public void setValue(Object obj) {
    this.obj = obj;
}

/**
 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 *
 * Method: getValue() description: get the next value of the currentNode
 *
 * @author Jinyu Wu Date: 2017/2/4
 * @return return next node
 */
public Node getNext() {
    if (nextNode != null) {
        return this.nextNode;
    } else {
        return null;
    }
}

/**
 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 *
 * Method: setNext() description: set next value for the Node
 *
 * @author Jinyu Wu Date: 2017/2/4
 * @param node set next node
 */
public void setNext(Node node) {
    this.nextNode = node;
}

}

问题在于
size()
方法中,您没有考虑两种边缘情况:

  • 当列表为空时(尝试执行
    n.getNext()

  • 当列表中只有一个节点时(它没有“next”,因此将返回零而不是1)

  • 通过在方法开头添加以下内容,可以轻松修复此问题:

    public int size() {
            int size = 1;
            if (firstNode == null) {
                return 0;
            }
            try {...
    
    方法
    add
    中存在另一个错误。for循环不必要地复杂,无法处理某些边缘情况。请将其修改为:

    public void add(int index, Object obj) {
        Node tempNode = firstNode;
        Node currentNode = new Node(obj);
        if (index < 0 || index > size()) {
            System.out.println("add(ObjectLinkedList) index out of bound exception: " + index + "; size: " + size());
        } else if (index == 0) {
            firstNode = currentNode;
        } else {
            for (int i = 0; i < index-1; i++) {
                tempNode = tempNode.getNext();
            }
            tempNode.setNext(currentNode);
        }
    }
    

    这样,当您打印列表时,您将能够看到所有元素,而不仅仅是第一个元素。

    我假设这是为了练习或分配,java已经有了
    LinkedList的通用实现

    您可能会发现java中许多关于数据结构的方法中的一种很有帮助,尽管它们的实现通常使用泛型而不是
    对象


    对于您的特定问题,您注意到在testAdd方法中您调用了

    assertEquals(list.get(0), m1);
    
    这是将
    节点
    与总是失败的
    货币
    对象进行比较

    您可以
    assertEquals(list.get(0).getValue(),m1);
    除非更改
    get()
    方法以返回
    节点,而不是当前执行的
    对象,否则此操作将不起作用

    其他测试也存在类似问题,其中
    list.get()
    返回一个
    节点,而不是该节点中的数据

    或者,编辑
    get()
    方法以返回节点中的数据:

        ...
        } else if (index == 0) {
            return firstNode.getValue();
        } else {
        // etc, you have multiple returns in this method
    
    编辑

    当get方法试图调用
    tempNode.getNext().getValue()
    时,您的
    testRemoveAt()
    将抛出一个
    NullPointerException
    ,但在测试删除第二个对象后,列表中只有一个Money对象,因此
    getNext()
    返回null

    编辑2

    对您来说,更熟悉调试器可能是最有用的。您可以尝试一个视频教程。然后您可以调查您的异常。例如,运行第一个测试可以提供:

    java.lang.AssertionError: 
    Expected :Node@4f2410ac
    Actual   :Money@722c41f4
    
    这意味着testAdd()测试在调用
    assertEquals(list.get(0),m1);

    这里需要注意的是,
    assertEquals
    的签名首先取预期值,然后取实际值。因此,将该行更改为
    assertEquals(m1,list.get(0));
    并重新运行测试

    现在输出为:

    java.lang.AssertionError: 
    Expected :Money@722c41f4
    Actual   :Node@4f2410ac
    
    因此,测试需要一个
    Money
    对象(这是
    m1
    参数),但是
    list.get(0)
    返回了一个
    节点
    对象

    要么测试预期的是错误的东西,要么
    get()
    方法返回的是错误的东西。我假设当调用
    list.get(0)
    时,您实际上想要拿回
    Money
    对象,这意味着测试是正确的,我们需要查看
    list.get()的实现

    你有:

    1.  public Object get(int index) {
    2.      if (index < 0 || index > size()) {
    3.          System.out.println("get(ObjectLinkedList) index out of bound exception");
    4.          return null;
    5.      } else if (index == 0) {
    6.          return firstNode;
    7.      } else {
    8.          Node tempNode = firstNode;
    9.          for (int i = 0; i <= index; i++) {
    10.             if (i == index - 1) {
    11.                 tempNode = tempNode.getNext();
    12.                 return tempNode;
    13.             }
    14.         }
    15.         System.out.println("objectLinkedList get method nothing found");
    16.         return null;
    17.      }
    18.  }
    

    然后再次运行
    testAdd
    ,它应该会通过

    这可能不会修复代码中的所有bug,但它为您提供了查找问题所需的步骤


    你的代码格式很好,你努力将javadoc放在你的函数上,而且你是持久的。做得好,坚持下去。

    节点
    是如何定义的?还有,你是如何调试代码的?你的发现是什么,你能提供一个行为仍然奇怪的较小的代码段吗?添加代码后,我得到了1个答案呃。应该是2,这是因为您在
    add
    中有另一个错误。请参阅更新的答案。我像您一样修改了我的代码l,但仍然存在错误。现在,我的add、find、removeAt和remove方法有问题。我想问题在于我的大小()方法,但我找不到error@JINYUWU问题是什么?尽量提供更多细节,否则很难帮助你。你好,我接受了你的建议,但现在我发现这些错误。我更新了我的问题。你能再接受一次吗?Thanks@JINYUWU确定你用的是什么IDE吗?我用的是NetBean谢谢,我遵循你的做法,它是p但是我的removeAt和remove方法有错误吗?因为我一直在获取NPEHi@JINYUWU。我在前面的第一次编辑中提到了这一点。这是因为代码试图调用
    getValue()
    null
    节点上进行调试。调试是一项非常有价值的技能,最好通过实践来学习,我建议您解决其他bug。
    java.lang.AssertionError: 
    Expected :Money@722c41f4
    Actual   :Node@4f2410ac
    
    1.  public Object get(int index) {
    2.      if (index < 0 || index > size()) {
    3.          System.out.println("get(ObjectLinkedList) index out of bound exception");
    4.          return null;
    5.      } else if (index == 0) {
    6.          return firstNode;
    7.      } else {
    8.          Node tempNode = firstNode;
    9.          for (int i = 0; i <= index; i++) {
    10.             if (i == index - 1) {
    11.                 tempNode = tempNode.getNext();
    12.                 return tempNode;
    13.             }
    14.         }
    15.         System.out.println("objectLinkedList get method nothing found");
    16.         return null;
    17.      }
    18.  }
    
    6.     return firstNode.getValue();
    
    12.    return tempNode.getValue();