【问题标题】:ArrayList add() method acting weird?ArrayList add() 方法行为怪异?
【发布时间】:2013-12-03 07:02:07
【问题描述】:

我正在使用“桶”实现(双)链表。简而言之,一个节点的双向链表,每个节点都持有一个 ArrayList,其大小由参数指定。

我已经初始化了我的节点和列表如下:

public class MyLinkedList<T> implements ADTListInterface<T> {

ArrayList<T> list;

private class Node {

    T value;
    Node next;
    Node previous;
    ArrayList<T> list;

    public Node(Node n, Node p) {

        list = new ArrayList<T>(bucketSize);
        next = n;
        previous = p;
    }
}

private Node head;
private Node tail;
private int bucketSize;

public MyLinkedList(int bucketSize) {

    this.bucketSize = bucketSize;
    head = tail = new Node(null, null);

}

我已经像这样设置了我的添加方法:

    public void add(T o) {

    Node current = head;

    while (current.list.add(o) != true) {

        if (current.next != null) {

            current = current.next;
        }

        if (current.next == null) {

            current.next = new Node(null,current);
        }
    }
}

在使用 bucketSize = 3 和以下命令测试 add 方法时:

list.add("a");
list.add("b");
list.add("c");

我希望头节点包含一个列表,其元素和顺序如下:

c,b,a

但是,current.list.add(o) 行似乎多次添加指定的对象,直到填满列表。所以我的节点原来包含元素:

一个,一个,一个

提前感谢您查看我的代码。

【问题讨论】:

  • ArrayList add 总是保证为真,不需要那个while循环。你应该能够做 current.list.add(o);然后进行检查以确保正确设置头部和尾部。
  • 几乎感觉像是在作弊;您正在使用已知的有效 ADT 来支持您的列表。您确定可以在代码中使用ArrayList
  • 我对 Java 编程还很陌生,我不确定 Makoto 的意思。作为这个项目的一部分,我得到了这个接口。据我了解,我需要填写类中接口中列出的每个方法。
  • 和 Bucco,我的想法是这样的;尝试将对象添加到第一个节点,如果不存在,则检查下一个节点是否存在,如果存在则尝试将其添加到那里,如果不存在则创建下一个节点然后尝试将其添加到那里。跨度>
  • 我明白了。但是,所有内容都将被推入第一个 ArrayList。传递给 ArrayList 构造函数 (bucketSize) 的值不是 ArrayList 的最大大小,而是实际上 ArrayList 内数组的起始大小。 ArrayList 将继续增长,您将始终添加到第一个 arraylist,永远不会添加到下一个。您可能需要考虑使用数组,而不是使用数组列表,因为大小是固定的。

标签: java arraylist computer-science


【解决方案1】:

部分问题在于打印列表内容的逻辑,部分问题在于您的 add 方法。首先,您当前的节点是 add 方法的局部变量。这意味着第二个“if”语句:

if (current.next != null) {

            current = current.next;
}

没有做任何有用的事情。您将 current 设置为指向与 current.next 相同的对象,但随后您离开该方法并且您的引用被破坏。这没有意义。

假设您调用了列表的构造函数,然后添加了三个元素:“a”、“b”、“c” 这是您的 Node 对象在堆上的行为方式。

构造函数完成后,堆上有一个 Node 对象,如下所示: { list -> {empty}, prev -> null, next -> null } 这个对象被 head 和 tail 引用变量引用。请注意,如果您调用 new ArrayList(bucketSize),它将创建具有 'bucketSize' 初始容量的空列表。

在第一次调用 add("a") 之后:

nodeObject#1 : { list -> {"a"}, prev -> null, next -> nodeObject#2 }

nodeObject#2 : { list -> {empty}, prev -> nodeObject#1, next -> null}

nodeObject#1 可以通过 head 或 tail 访问。 nodeObject#2 可通过 head.next 或 tail.next 访问。

在第二次调用 add("b") 之后:

nodeObject#1 : { list -> {"a","b"}, prev -> null, next -> nodeObject#2 }

nodeObject#2 : { list -> {empty}, prev -> nodeObject#1, next -> null}

在第三次调用 add("c") 之后:

nodeObject#1 : { list -> {"a","b","c"}, prev -> null, next -> nodeObject#2 }

nodeObject#2 : { list -> {empty}, prev -> nodeObject#1, next -> null}

在您的节点中还有 prev 和 next 建议您的列表应该是双向的,这意味着您需要实现 add_at_the_end 和 add_at_the_beginning 等方法,但这是另一回事(如果需要,我也可以展示一些示例)。 下一个问题是为什么使用 ArrayList 作为 Node 类字段。 T值应该够了。

这是我没有 ArrayList 的简单列表实现示例。有一个迭代器方法,它返回可用于显示列表元素的迭代器实例。

package com.playground;

import java.util.ArrayList;
import java.util.Iterator;

class CustomList<T>{
    private class Node{
        Node prev;
        Node next;

        T value;
        Node(T rVal, Node p, Node n){
            this.value = rVal;
            this.prev = p;
            this.next = n;
        }
        void setNext(Node n){ this.next = n; }
        void setPrev(Node p){ this.prev = p; }
    }

    private Node head;
    private Node tail;



    public void add(T element) {
        if(tail == null && head == null){
            head = new Node(element, null,null);
            tail = head;
        }
        else{
            Node tmp = new Node(element, tail, null);
            tail.setNext( tmp );
            tail = tmp;
        }

    }

    public Iterator<T> iterator() {

        return new Iterator<T>(){
            Node current = head;
            @Override
            public boolean hasNext() {
                // TODO Auto-generated method stub
                return current != null;
            }

            @Override
            public T next() {
                Node tmp = current;
                current = tmp.next;
                return tmp.value;
            }

            @Override
            public void remove() {
                // TODO Auto-generated method stub

            } };
    }

}

public class CustomListTest {
    public static void main(String [] args){
        CustomList<String> list = new CustomList<String>();
        list.add("my");
        list.add("custom");
        list.add("list");       

        Iterator<String> forwardIterator = list.iterator();
        while( forwardIterator.hasNext()){
            System.out.println( forwardIterator.next());
        }

    }
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2013-04-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-10-02
    • 1970-01-01
    • 1970-01-01
    • 2013-10-11
    相关资源
    最近更新 更多