为什么我的自定义LinkedList不起作用?

时间:2017-02-06 05:12:18

标签: java data-structures collections linked-list nodes

我正在尝试创建自定义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;

}

}

以下是使用Junit测试

进行测试的内容
package numberlist.primitivelist.objectlist;

import org.junit.Before;
import org.junit.Test;
import static org.junit.Assert.*;


public class ObjectLinkedListTest {

ObjectLinkedList list;
Money m1, m2;
Node node1, node2;

public ObjectLinkedListTest() {

}

@Before
public void setUp() {
    list = new ObjectLinkedList();
    m1 = new Money(5, (byte) 6);
    node1 = new Node(m1);
    list.add(0, node1);

    m2 = new Money(2, (byte) 4);
    node2 = new Node(m2);
    list.add(1, node2);
}

/**
 * Test of add method, of class ObjectLinkedList.
 */
@Test
public void testAdd() {
    assertEquals(list.get(0), node1);
}

/**
 * Test of removeAt method, of class ObjectLinkedList.
 */
@Test
public void testRemoveAt() {
    list.removeAt(1);
    assertNull(list.get(1));
}

/**
 * Test of remove method, of class ObjectLinkedList.
 */
@Test
public void testRemove() {
    list.remove(m2);
    assertNull(list.get(1));
}

/**
 * Test of get method, of class ObjectLinkedList.
 */
@Test
public void testGet() {
}

/**
 * Test of toString method, of class ObjectLinkedList.
 */
@Test
public void testToString() {
}

/**
 * Test of find method, of class ObjectLinkedList.
 */
@Test
public void testFind() {
    assertEquals(list.find(m1), 0);
    assertEquals(list.find(m2), 1);
}

/**
 * Test of size method, of class ObjectLinkedList.
 */
@Test
public void testSize() {
    assertEquals(list.size(), 2);
}

/**
 * Test of deepCopy method, of class ObjectLinkedList.
 */
@Test
public void testDeepCopy() {

}

}

这是我得到的错误:

Error here

我的节点类:

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;
}

}

2 个答案:

答案 0 :(得分:0)

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

  1. 当列表为空时(您将获得NPE以尝试执行n.getNext()

  2. 当列表中只有一个节点时(它没有“下一个”,所以它将返回零而不是1)

  3. 您可以通过在方法开头添加以下内容轻松修复它:

    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);
        }
    }
    

    代码可以运行。

    此外,我还会将toString方法“升级”为:

    @Override
    public String toString() {
        Node tmp = firstNode;
        String res = "" + firstNode;
        while (tmp.getNext() != null) {
            tmp = tmp.getNext();
            res += "," + tmp;
        }
        return "ObjectLinkedList{" + res + "}";
    }
    

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

答案 1 :(得分:0)

我认为这是为了练习或分配,java已经LinkedList的通用实现see the api docs

您可以在java helpul中找到许多texts数据结构中的一个,但通常它们的实现使用泛型而不是Object

针对您的具体问题,您会注意到在testAdd方法中调用

assertEquals(list.get(0), m1);

这是将NodeMoney对象进行比较,该对象始终会失败。

你可以assertEquals(list.get(0).getValue(), m1); 除非你改变get()方法以返回Node而不是Object,否则这不会有效做。

您遇到与其他测试类似的问题,其中list.get()返回Node,而不是该节点内的数据。

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

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

修改

当get方法尝试调用testRemoveAt()时,NullPointerException将抛出tempNode.getNext().getValue(),但在测试删除第二个对象之后,列表中只有一个Money对象getNext() java.lang.AssertionError: Expected :Node@4f2410ac Actual :Money@722c41f4 assertEquals(list.get(0), m1); 1}}返回null。

修改2

您可能最熟悉调试器。也许试试netbeans的视频教程。然后,您调查您的例外情况。例如,运行第一个测试会给出:

assertEquals

这意味着testAdd()测试在调用assertEquals(m1, list.get(0));

时失败

此处需要注意的是java.lang.AssertionError: Expected :Money@722c41f4 Actual :Node@4f2410ac 的签名首先取其预期值,然后取实际值。因此,将该行更改为Money并重新运行测试。

现在输出是:

m1

因此测试期望list.get(0)个对象(即Node参数),但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. } 对象,这意味着测试正确,我们需要看一下执行Node

你有:

Money

在第6和第12行,你可以看到问题:当我们真正想要Node时,函数返回6. return firstNode.getValue(); ;或者更具体地说,12. return tempNode.getValue(); 作为对象的值。因此,可以对这些行进行以下更改

testAdd

jsonp

然后再次运行beforeSend它应该通过。

这可能修复代码中的所有错误,但它会让您了解要找到问题的步骤。

您的代码格式正确,您已经努力将javadoc放在您的函数上,并且您将继续执行。干得好,坚持下去。