Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/368.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?_Java_Algorithm_Arrays_List - Fatal编程技术网

Java 没有复制开销的ArrayList?

Java 没有复制开销的ArrayList?,java,algorithm,arrays,list,Java,Algorithm,Arrays,List,有人知道有一个实现具有恒定的时间get(int-index)(即implements),但在它增长时不必复制整个列表吗 我认为实施很可能是在其他列表方面,例如 public class ChunkedList<T> implements List<T>, RandomAccess { private LinkedList<ArrayList<T>> chunks; public T get(int index) { return f

有人知道有一个实现具有恒定的时间get(int-index)(即implements),但在它增长时不必复制整个列表吗

我认为实施很可能是在其他列表方面,例如

public class ChunkedList<T> implements List<T>, RandomAccess {
  private LinkedList<ArrayList<T>> chunks;
  public T get(int index) {
    return findCorrectChunk(index).get(computeChunkIndex(index));
  }
}
public类ChunkedList实现列表、随机访问{
私有链接列表块;
公共T获取(整数索引){
返回findCorrectChunk(index).get(computeChunkIndex(index));
}
}

嗯,这并不是一个理想的解决方案,但您可以使用TreeMap来实现这一点。你的ChunkedList将是围绕这一点的一个警告。树映射中的键将是Integer或Long类型,并将保存列表索引。访问和插入时间将是o(log(n))(不是常数,但比n好得多)。在内部,TreeMap的工作原理与LinkedList类似,即节点仅与引用链接

编辑:类似的内容:

public class ChunkedList<T> implements List<T>, RandomAccess {

    private TreeMap<Integer, T> data = new TreeMap<Integer, T>();

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

    public boolean add(T o) {
        data.put(data.size() + 1, o);
        return true;
    }

       // Other operations

}
public类ChunkedList实现列表、随机访问{
私有树映射数据=新树映射();
公共T获取(整数索引){
返回数据。获取(索引);
}
公共布尔加法(TO){
data.put(data.size()+1,o);
返回true;
}
//其他业务
}

当然,与ArrayList中的操作相比,其他操作会稍微复杂一些,并且需要更长的时间。

如果有这样的结构,每个人都会使用它而不是数组

然而,我认为一个更紧密的结构,我在一次大学演讲中被告知。它有一个恒定的访问时间,向任意位置添加/删除元素的时间主要是O(sqrt(N)),只有当N与整数值的平方相交时,才需要O(N)。摊销时间为O(sqrt(N))。这是我的想法

此结构中的N个项存储在一个连续数组中,该数组被划分为sqrt(N)个连续元素的sqrt(N)块(可能最后一个块包含较少的元素)。每个块都是一个数组,第一个元素的位置存储在一个单独的sqrt(N)数组中。要访问一个元素,您应该确定它所在的块(需要一个除法),并在环形缓冲区内进行适当的移位(求和和和模)。这是一个固定的访问时间

要在第i个位置之前添加元素,请确定元素将结束的块
k
,然后在
k
范围内标记每个块中的所有最后元素。
sqrt(N)-1
。将pre-last chunk中标记的元素移动到最后一个chunk中的空闲插槽,该插槽将是该区块中环形缓冲区的头部(访问其他数组以确定确切位置)。然后将标记的元素从pre-last chunk移动到从pre-last chunk移动的元素的位置。重复这个,你会在数组中间得到一个空闲的插槽来放置你要添加的元素。 神奇的是,您应该只将额外数组中的值增加一(需要O(sqrt(N))时间),从而使结构一致,以便再次访问。sqrt(N)的魔力也在这里:您应该对辅助数组的每个X块和每个N/X元素进行操作。对于X=sqrt(N),达到最小值(X+N/X)

如果最后一个块中没有地方再添加一个元素(,即到目前为止使用的sqrt(N)太小),请使用增加1的sqrt(N)重新打包数组。这需要O(N)个时间。每个元素的摊销时间仍然为O(sqrt(N))

因此,在数组的任意位置添加元素需要O(sqrt(N))。删除需要相同的时间。访问时间为0(1)


这就是我的想法。我不知道它叫什么,教授也不知道,因为这是他自己发明的。如有任何参考,将不胜感激。OP可以实现它,但我敢打赌,已经有人实现了。

当然,您可以将列表实现编写为数组数组。关于精确的算法有很多选择。性能在理论上是恒定的(忽略缓存效果等)

实际上,在大多数情况下没有太多的意义。有rope实现(字符串形成为段数组),但是这些实现相对较少。拷贝并没有那么贵,对于附件来说,它是在许多操作中摊销的,以便消失


(顺便说一句,在问题示例代码中,
LinkedList
几乎总是不合适的。)

您是否只考虑过向ArrayList构造函数暗示最大大小?

查看一下随机访问列表。您可以在两端获得O(1)插入和O(log(n))对元素的访问


最后,某种类似树的结构应该提供最佳的查找/插入时间。

这听起来像是过早的优化。您是否分析了
add()
函数并显示它很慢?因为
ArrayList
每当底层数组耗尽空间时,它的大小都会翻倍,所以不必每次追加时都复制列表


您可能正在尝试解决一个不存在的问题。

编写这样的数据结构是不可能的。最接近的方法是在已知最大值的情况下,将ArrayList的大小预先设置为最大值。有趣的是,Collections.sort()等算法在
ChunkedList
上的性能将更差,如果其标记为
RandomAccess

那么,您有一个列表,需要定期扩展列表并按索引从中删除元素?好的,ArrayList在超出其当前容量时会将其容量加倍。因此将有O(log(n))个拷贝,其中n是列表的最终容量。这意味着需要复制整个列表的实际次数确实非常少。在开销变得显著之前,您可能早就开始耗尽内存了。OTOH,如果您必须停止复制并提前知道列表必须包含的元素数的上限,那么您可以将max size作为参数传递给ArrayL