Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/306.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 循环ArrayList(扩展ArrayList)_Java_Arraylist_Extending_Circular List - Fatal编程技术网

Java 循环ArrayList(扩展ArrayList)

Java 循环ArrayList(扩展ArrayList),java,arraylist,extending,circular-list,Java,Arraylist,Extending,Circular List,所以我的程序需要一种循环数组列表 唯一循环的是get(int index)方法,这是原始的: /** * Returns the element at the specified position in this list. * * @param index index of the element to return * @return the element at the specified position in this list

所以我的程序需要一种循环数组列表

唯一循环的是get(int index)方法,这是原始的:

    /**
     * Returns the element at the specified position in this list.
     *
     * @param  index index of the element to return
     * @return the element at the specified position in this list
     * @throws IndexOutOfBoundsException {@inheritDoc}
     */ 
    public E get(int index) {
        rangeCheck(index);

        return elementData(index);
    }
如果索引为-1,则应获取索引为ArrayList.size()-1的元素;如果索引为ArrayList.size(),则应获取索引为0的元素

我想到的实现这一点的最简单方法就是从java.util包中扩展ArrayList,并重写get(int index),这样就不会对上面的两个索引抛出IndexOutOfBoundsException,而是将它们更改为我想要的。它会对任何超出范围的其他索引抛出IndexOutOfBoundsException

但是,由于elementData(索引)访问

我不能让它工作,因为我的班级没有看到它,因为它是私人的

此外,我不想为此使用任何外部库,只是因为我认为没有一个库适合我的需要,因为我不想要真正的circularArray,而只是它的一部分功能,其余部分是常规ArrayList

所以我有两个问题:

我怎样才能做到这一点?有没有办法不将整个ArrayList类以及AbstractCollection、Collection和Iterable复制到我的程序中?即使对我来说,这似乎也是个糟糕的设计

如果我能设法让它工作,还有什么我应该注意的吗?如果我做了上面描述的更改,会不会只按我希望的方式更改类的行为,或者会有任何其他不希望的行为更改

编辑: 谢谢你的回答,以下是我所做的:

import java.util.ArrayList;

public class CircularArrayList<E> extends ArrayList<E>
{
    private static final long serialVersionUID = 1L;

    public E get(int index)
    {
        if (index == -1)
        {
            index = size()-1;
        }

        else if (index == size())
        {
            index = 0;
        }

        return super.get(index);
    }
}
import java.util.ArrayList;
公共类循环raylist扩展了ArrayList
{
私有静态最终长serialVersionUID=1L;
公共E-get(int索引)
{
如果(索引==-1)
{
索引=大小()-1;
}
else if(index==size())
{
指数=0;
}
返回super.get(索引);
}
}

它将环绕ArrayList,但只环绕一个。如果我试图访问除第一个和最后一个元素之外的任何其他元素,除了它们的常规ArrayList索引,我希望它抛出一个异常。

您描述的基本上是获取所需索引的模数,并在列表中访问该元素

您可以通过组合而不是继承执行以下操作:

  • 为接口
    List
    创建一个包装器类,现在我们称它为ListWrapper
    • 添加接受列表实例的构造函数
    • 让列表实例受到保护,并将其命名为
      wrapped
  • 扩展包装器类
为什么要做这些废话?这与实现无关。有一天,您可能希望在另一个实现中使用这种便利性。然后你必须复制代码,地狱开始了。如果您也需要第三个实现,然后只添加一点点新功能,那么您注定要失败

使用介于以下两者之间的包装器类:

  • 您可以让所有实现List接口的类都具有自己的功能
  • 您可以在一个地方更改包装器类
  • 您将能够在一个位置添加新功能
记住,我们编写的程序必须是可维护的

包装类

public abstract class ListWrapper<T> implements List<T> {
    protected final List<T> wrapped;

    public ListWrapper(List<T> wrapped) {
        this.wrapped = wrapped;
    }

    public T get(int index) {
        return wrapped.get(index);
    }

    //omitting the other wrapper methods, for sake of brevity.
    //Note: you still have to add them.
    // Eclipse: Source menu, Generate Delegate methods does the trick nicely
}
public class ModList<T> extends ListWrapper<T> {

    public ModList(List<T> list) {
        super(list);
    }

    @Override
    public T get(int index) {
        int listSize = wrapped.size();
        int indexToGet = index % listSize;

        //this might happen to be negative
        indexToGet = (indexToGet < 0) ? indexToGet+listSize : indexToGet;
        return wrapped.get(indexToGet);
    }

}
公共抽象类ListWrapper实现列表{
受保护的最终清单;
公共ListWrapper(列表包装){
this.wrapped=wrapped;
}
公共T获取(整数索引){
返回包装的.get(索引);
}
//为了简洁起见,省略了其他包装器方法。
//注意:您仍然需要添加它们。
//Eclipse:源代码菜单,生成委托方法很好地实现了这一点
}
现在是真正的新课程

public abstract class ListWrapper<T> implements List<T> {
    protected final List<T> wrapped;

    public ListWrapper(List<T> wrapped) {
        this.wrapped = wrapped;
    }

    public T get(int index) {
        return wrapped.get(index);
    }

    //omitting the other wrapper methods, for sake of brevity.
    //Note: you still have to add them.
    // Eclipse: Source menu, Generate Delegate methods does the trick nicely
}
public class ModList<T> extends ListWrapper<T> {

    public ModList(List<T> list) {
        super(list);
    }

    @Override
    public T get(int index) {
        int listSize = wrapped.size();
        int indexToGet = index % listSize;

        //this might happen to be negative
        indexToGet = (indexToGet < 0) ? indexToGet+listSize : indexToGet;
        return wrapped.get(indexToGet);
    }

}
public类ModList扩展ListWrapper{
公共ModList(列表){
超级(名单);
}
@凌驾
公共T获取(整数索引){
int listSize=wrapped.size();
int indexToGet=索引%listSize;
//这可能是负面的
indexToGet=(indexToGet<0)?indexToGet+列表大小:indexToGet;
返回包装。获取(索引);
}
}
当心

  • 但是,这对于多线程环境来说并不安全
  • 对原始列表的所有实例都要小心——如果你改变了它,ModList实例也会改变

难道您不能从ArrayList派生并重写get(int index)方法吗

@Override
public E get(int index)
{
    if(index < 0)
        index = index + size();

    return super.get(index);
}
@覆盖
公共E-get(int索引)
{
如果(指数<0)
索引=索引+大小();
返回super.get(索引);
}
我错过了什么


请注意,此实现不会将任意索引折叠到有效的索引范围中,只允许从左侧和右侧正确地处理列表(分别使用正索引和负索引,有点像Python中的索引).

您可以扩展ArrayList类来更改
get
方法的功能,而无需访问
elementData
字段:

public class CircularList<E> extends ArrayList<E> {

    @Override
    public E get(int index) {
        return super.get(index % size());
    }
}
公共类循环列表扩展了ArrayList{
@凌驾
公共E-get(int索引){
返回super.get(索引%size());
}
}
super.get
方法仍将执行范围检查(但这些检查永远不会失败)


您应该知道,这样做会使ArrayList索引不稳定。如果列表的大小发生变化,则正常范围之外的所有索引都将发生变化。例如,如果您有一个列表
['a','b','c','d','e']
,那么
get(7)
将返回
c
。如果您随后执行
add('f')
,那么
get(7)
将突然返回
b
,因为
get
现在将以模6而不是模5工作。

有人知道这个抽象列表扩展名:
com.sun.apps吗