如何将对象添加到链表中?

5

我一直在一个项目上工作,必须实现一个使用双向链表的java类。我已经完成了LinkedList类和其中的所有方法。我只是不知道如何将节点对象添加到列表中。以下是我的代码及其底部的测试。非常感谢您的帮助。

public class LinkedList {

    private Node first;
    private Node current;
    private Node last;
    private int currentIndex;
    private int numElements;

    public LinkedList() {
        this.first = null;
        this.last = null;
        this.numElements = 0;
        this.current = null;
        this.currentIndex = -1;
    }

    private class Node {

        Node next;
        Node previous;
        Object data;
    }

    public boolean hasNext() {
        return (current != null && current.next != null);
    }

    public Object next() {
        if (!this.hasNext()) {
            throw new IllegalStateException("No next");
        }

        current = current.next;
        return current.data;

    }

    public boolean hasPrevious() {
        return (current != null && current.previous != null);

    }

    public Object previous() {
        if (!this.hasPrevious()) {
            throw new IllegalStateException("No previous");
        }
        current = current.previous;
        return current.data;

    }

   int nextIndex() {
        int index = numElements;
        if (hasNext()) {
            index = this.currentIndex + 1;
        }
        System.out.println(index + "The current index is " + current);
        return index;
    }

    int previousIndex() {
        int index = -1;
        if (hasPrevious()) {
            index = this.currentIndex - 1;
        }
        System.out.println(index + "The current index is " + current);
        return index;
    }

    public void set(Object o) {
        if (this.current == null) {
            throw new IllegalStateException("No node found, cannot set.");
        }
        current.data = o;
    }

    public int size() {
        return numElements;
    }

    public void add(Object o) {       
        Node newNode = new Node();
        newNode.data = o;
        if (first == null) {
            first = newNode;
            last = newNode;
            newNode.next = null;

        } else if (first != null) {
            if (current == null) {
                newNode.previous = null;
                newNode.next = first;
                first.previous = newNode;
                first = newNode;
            } else if (current == last) {
                newNode.previous = current;
                newNode.next = null;
                current.next = newNode;
                last = newNode;
            } else {
                newNode.previous = current;
                newNode.next = current.next;
                current.next.previous = newNode;
                current.next = newNode;
            }
        }
        current = newNode;
        numElements++;
        currentIndex++;

    }

    public void remove() {
        if (current != null) {
            if (current == first && current == last) {
                first = null;
                last = null;
            } else if (current == last) {
                current.previous = null;
                last = current.previous;
            } else if (current == last) {
                current.previous.next = null;
                last = current.previous;
            } else {
                current.previous.next = current.next;
                current.next.previous = current.previous;
            }
            current = current.next;
            numElements--;
        }
    }
}



import java.util.Scanner;


public class LinkedListTest {
    public static void main(String[] args) {
        Scanner keyboard = new Scanner(System.in);
        String name;
        int index;

        LinkedList<Object> listOne = new LinkedList<Object>();

        listOne.add(object o);

    }
}

2
抱歉关于测试类,我知道它很糟糕。 - joe
1
看起来你目前走在正确的轨道上。你的输出结果是什么,你期望得到什么? - Cliff
我不明白输出错误的原因,错误信息显示“LinkedList类型不接受参数”。 - joe
@joe 这是因为你的 LinkedList 不是泛型,所以你不能用 <Object> 参数化它。 - Kakalokia
@Johannes Weiß:请查看作业标签维基。 - Mat
显示剩余3条评论
7个回答

4

我认为所发布的LinkedList类很实用。

请确保你的测试代码不会混淆这个类和Java已经提供给你的java.util.LinkedList(它是现有集合框架的一部分)。

为了使其更加清晰,我建议将你的类重命名为像MyLinkedList这样的名称。

以下代码可以工作,并且输出结果是“0”,“2”:

public class MyLinkedListTest {

    public static final void main(String[] args) {

        MyLinkedList list = new MyLinkedList();
        System.out.println("Number of items in the list: " + list.size());

        String item1 = "foo";
        String item2 = "bar";

        list.add(item1);
        list.add(item2);

        System.out.println("Number of items in the list: " + list.size());      

        // and so on...
    }

}

这似乎是最好的方法。谢谢。 - joe

2

如果你的类不是真正的泛型,那么我会感到惊讶,因此我认为你的代码不会编译。只需将其初始化为LinkedList listOne = new LinkedList();(没有尖括号)。

至于实际添加元素,你只需要一个Object实例即可添加;任何东西都可以(假设你的内部代码正常工作)。在那里尝试一下这个:

Object objectToAdd = "Strings are Objects";
listOne.add(objectToAdd);
objectToAdd = new File("C:\\foo.bar"); // Or use any other Objects!
listOne.add(objectToAdd);

我也发现了这个问题。他可能需要小心,因为有些IDE会自动导入Java的LinkedList,这可能会导致混淆。 - Cliff
@Cliff 我猜他没有使用集成开发环境,否则它会警告他 listOne.add(object o); 无法编译,但这确实是一个有效的问题。 - Henry Keiter
没错,但是如果他是编程新手,很可能没有注意到警告而继续输入了代码。 - Cliff

1

想一下有序列表,并查看元素之间的关系。

假设我有以下列表:

  1. A
  2. B
  3. C

如果我要在列表中添加一个NewNode,需要进行的操作是什么?

  1. A
  2. B
  3. NewNode
  4. C

B的新下一个节点是NewNode,C的新上一个节点是NewNode。因此,插入函数需要知道前一个节点或后一个节点,并调整它们之间的关系。


这与他的问题有何关联? - Henry Keiter
@HenryKeiter "如何将对象添加到链表中?" 显然这是一道作业题,因此我用英语解释了如何操作,而非代码。 - Philip Whitehouse
1
他已经有了那段代码。他真正询问的是如何实例化列表并向其中添加对象。这是一个语法问题,而不是实现问题。 - Henry Keiter

1

你的 LinkedList 没有泛型,因此你不能将其声明为

LinkedList<Object> listOne = new LinkedList<Object>();

但是,更确切地说是:

LinkedList listOne = new LinkedList();

现在要添加元素,只需使用您的add方法。
listOne.add("something");
listOne.add(1);//int will be autoboxed to Integer objects

此外,如果您想从键盘添加数据,可以使用类似以下的内容。
String line="";
do{
    System.out.println("type what you want to add to list:");
    line = keyboard.nextLine();
    listOne.add(line);
}while(!line.equals("exit"));

这个代码是有效的,而且我以前写过类似的代码,但如果我使用字符串“Something”或整数1,它们是否被认为是对象? - joe
1
@joe String 是一个类,所有的类最终都会扩展 Object 类,以便它们的实例可以被视为对象。在 1 的情况下,它是原始类型 int,但在这种情况下,当您将原始类型作为期望对象的参数使用时,它将被 自动装箱Integer,它也最终扩展了 Object,因此它可以正常工作。 - Pshemo

0

这行代码

LinkedList<Object> listOne = new LinkedList<Object>();

如果你不改变类声明,将无法编译通过。

你需要将类声明更改为

class LinkedList<T>

或者你可以直接写

LinkedList listOne = new LinkedLis();

之后,你就可以向列表中添加对象了。但是,你需要创建一个对象来添加到列表中,listOne.add(object o); 是不行的——至少你需要写 listOne.add(new Object())。(你的代码没有实例化一个对象,也没有叫做o的对象,而且,在Java中,object o 没有任何意义,也无法编译通过。)


我明白了。所以如果我创建一个类,比如说汽车。我是需要每次都创建一个新的汽车,还是可以使用默认构造函数将多个相同的默认汽车添加到列表中? - joe
你肯定可以将多个相同的默认汽车添加到列表中,但你究竟想要实现什么?为什么你想要一个完全相同的汽车对象列表? - Catherine
1
更重要的是,如果您多次将同一对象实例添加到列表中,例如,您如何验证对象是否被正确地按正确顺序添加?您列表中的所有对象看起来都是相同的,您将无法从中获得任何信息。 - Catherine

0

正如其他人所提到的,您的列表不是通用的。然而,当他们建议您摆脱参数时,您也可以只将<Object><E>添加到您的链表实现中,并保留列表的初始化。

因此,在您的链表类中,您应该这样做:

public class LinkedList<E>

这将确保当您使用 LinkedList<Object> listOne = new LinkedList<Object>(); 时,E 将被转换为 Object


0

让我们稍微改进一下您的测试,以便能够清楚地看出您的问题所在(如果有的话)。我已经将对current()方法的调用注释掉了,因为您没有包含它。(我建议保持不变,以免混淆您。)一般的想法是向链表中添加项目,并向前和向后遍历它,每一步都检查项目。

public class LinkedListTest {
    public static void main(String[] args) {
        Scanner keyboard = new Scanner(System.in);
        String name;
        int index;

        LinkedList listOne = new LinkedList();
        //Initially we should be empty so we are positioned
        // at both the beginning and end of the list
        assert listOne.size() == 0 :"List should be empty";
        assert listOne.hasPrevious()==false: "Should be at the beginning of the list";
        assert listOne.hasNext()==false : "Should be at the end of the list";

        Object firstNode = "I am the first node";
        listOne.add(firstNode); //we've added something
//I left this commented out since you don't have a current() method.
//        assert firstNode == listOne.current() : "Our current item should be what we just added";
        assert listOne.hasPrevious()==false : "Should not have moved forward in our list yet";
        assert listOne.hasNext()==true : "should have an item after our current";
        assert listOne.size() == 1 : "Should only have one item in the list";
        Object secondNode = "I am the second node";
        listOne.add(secondNode);
        assert listOne.size() == 2 : "Should only have two items in the list";

        assert firstNode == listOne.next() : "1st call to next should return the 1st node";
        assert listOne.hasPrevious()==true : "We should be positioned after the 1st node";
        assert listOne.hasNext()==true : "We should be positioned before the 2nd node";
    }
}

在Java中,使用Assert是常见的做法吗?# - joe
这取决于你的雇佣情况! :D 我在这里使用断言来说明代码的预期工作方式。许多人会使用完整的JUnit框架来完成相同的工作。无论哪种方式,您都可以获得调试代码的好处,而不使用调试器,采用增量式解决方案发现方法,并且具有永远不会过时的内置文档。 - Cliff

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接