【问题标题】:Implementing custom LinkedArrayList with extending AbstractList通过扩展 AbstractList 实现自定义 LinkedArrayList
【发布时间】:2020-03-27 02:39:56
【问题描述】:

问题定义

  • 我需要一个包含节点的集合,并且每个节点都有一个固定大小的部分填充数组。每个数组可以包含不同的大小,只要小于之前定义的常量大小即可。会有这些节点的列表。

例如:

  • 当需要将一个元素添加到列表中时,列表会在第一个未满的适当节点处添加一个元素。如果我连续 add(1) , add(2) , add(3) , add(4) , add(1) , 列表会这样展示:
  • 假设DEFAULT_NODE_CAPACITY = 3
    • node-0 -> "123"
    • node-1 -> "41"

  • 当需要从列表中删除一个元素时,列表会从包含给定元素并与之匹配的第一个适当节点中删除一个元素。如果我从列表中 remove(1) ,列表将显示如下:
    • node-0 -> "23"
    • node-1 -> "41"

我尝试了什么?

  • 我考虑过使用静态内部类,因为节点类不应该访问外部类的字段和方法。所有类型都必须是通用的,所以我为每个构造函数设置了相同的通用键值。
  • 关键点是我必须在我的自定义集合中使用 AbstractList 类。此时我真的很困惑我将使用什么结构来调用具有部分固定数组的节点类。

问题

  • 如何覆盖符合我的节点内部类的 AbstractList 方法。当我阅读 Java API Documentation 时,为了创建可修改我只需要覆盖

    • get()
    • set()
    • 删除()
    • add()
    • 尺寸() 在这一点上,我怎样才能通过符合我的问题定义来有效地覆盖所有这些?
  • 我应该使用什么数据类型来调用 Node<E> ?以及如何实现?


我是如何实现的?

package edu.gtu.util;

import java.util.AbstractList;
import java.util.Collection;
import java.util.List;

public class LinkedArrayList<E> extends AbstractList<E>
        implements List<E> , Collection<E>, Iterable<E> {

    public static final int DEFAULT_CAPACITY = 10;
    public static final int CONSTANT_NODE_CAPACITY = 3;

    /* Is that wrong ? , how to be conformed to AbstractList ? */
    private Node<E>[] listOfNode = null;
    /*---------------------------------------------------------*/

    private int size;

    private static class Node<E> {

        private Object[] data;
        private Node<E> next = null;
        private Node<E> previous = null;

        private Node( Object[] data , Node<E> next , Node<E> previous ) {

            setData(data);
            setNext(next);
            setPrevious(previous);

        }

        private Node( Object[] data ) {
            this( data , null , null );
        }

        private void setData( Object[] data ) {
            this.data = data;
        }
        private void setNext( Node<E> next ) {
            this.next = next;
        }
        private void setPrevious( Node<E> previous ) {
            this.previous = previous;
        }

        private Object[] getData() {
            return data;
        }
        private Node<E> getNext() {
            return next;
        }
        private Node<E> getPrevious() {
            return previous;
        }

    }


    private void setSize( int size ) {
        this.size = size;
    }

    public LinkedArrayList() {
        super();
    }

    public LinkedArrayList( int size ) {
        super();

        setSize( size );
        listOfNode = (Node<E>[]) new Object[size()];
    }

    public LinkedArrayList(Collection<E> collection ) {
        super();
    }

    @Override
    public E get( int i ) {
    }

    @Override
    public boolean add(E e) {
        return super.add(e);
    }

    @Override
    public boolean remove(Object o) {
        return super.remove(o);
    }

    @Override
    public E set(int index, E element) {
        return super.set(index, element);
    }

    @Override
    public int size() {
        return size;
    }

}

【问题讨论】:

  • 小心点。正如文档所述,您必须覆盖 get(int)set(int, E)add(int, E)remove(int),而不仅仅是一些 addremove 方法。覆盖意味着填充实际的实现,而不仅仅是执行super 调用,就像该方法从未被覆盖一样。实施取决于您,这是您的任务。

标签: java arrays list collections linked-list


【解决方案1】:

首先,您需要向Node 添加一个字段,告诉您该节点中存储了多少数据项。

然后:

  • size 必须遍历节点并计算节点大小的总和。或者您可以保持一个单独的大小,并在每次添加和删除时更新它。

  • add 必须找到可以插入项目的节点。如果该节点中有空间,只需将其添加到那里。如果该节点已满,则必须创建一个新节点。

  • remove 必须找到正确的节点并从该节点中删除项目。如果节点为空,则可以删除节点本身。

  • get 必须遍历节点,跟踪它跳过了多少项,直到找到必须包含该节点的节点。

  • set - 与get 相同,不同之处在于它会替换该项目并返回它

您会在维基百科中找到更好的描述:https://en.wikipedia.org/wiki/Unrolled_linked_list 本文还建议对添加/删除进行重要优化。

【讨论】:

    猜你喜欢
    • 2023-03-13
    • 1970-01-01
    • 2013-09-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-04-10
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多