ArrayList add()方法行为怪异吗?

时间:2013-12-03 07:02:07

标签: java arraylist computer-science

我正在使用“存储桶”处理(双)链表实现。简而言之,一个双向链接的节点列表,每个节点都包含一个由参数指定的集合大小的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");

我希望head节点包含一个包含元素和顺序的列表,如下所示:

C,B,A

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

A,A,A

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

1 个答案:

答案 0 :(得分:1)

您的部分问题在于打印列表内容的逻辑,部分内容在您的add方法中。首先,您当前的节点是add方法的局部变量。这意味着第二个'如果'声明:

if (current.next != null) {

            current = current.next;
}

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

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

构造函数完成后,堆上有一个Node对象,如下所示: {list - &gt; {empty},prev - &gt; null,next - &gt; null}此对象由头部和尾部引用变量引用。请注意,如果您调用新的ArrayList(bucketSize),它将创建具有'bucketSize'初始容量的空列表。

第一次加注(“a”)后:

nodeObject#1:{list - &gt; {“a”},prev - &gt; null,next - &gt; nodeObject#2}

nodeObject#2:{list - &gt; {empty},prev - &gt; nodeObject#1,next - &gt;空}

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

第二次加注(“b”)后:

nodeObject#1:{list - &gt; {“a”,“b”},prev - &gt; null,next - &gt; nodeObject#2}

nodeObject#2:{list - &gt; {empty},prev - &gt; nodeObject#1,next - &gt;空}

第三次调用add(“c”)后:

nodeObject#1:{list - &gt; {“a”,“b”,“c”},prev - &gt; null,next - &gt; nodeObject#2}

nodeObject#2:{list - &gt; {empty},prev - &gt; nodeObject#1,next - &gt;空}

你的Node中还有prev和next表明你的列表应该是双向的,这意味着你需要实现add_at_the_end和add_at_the_beginning等方法,但这是一个不同的故事(如果需要,我也可以展示一些例子)。 接下来的问题是为什么使用ArrayList作为Node类字段。 T值应该足够了。

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

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

    }
}