ArrayList如何在恒定时间内检索数据?

时间:2018-08-27 21:11:10

标签: java arraylist

一个面试问题,我无法回答,也无法在线找到任何相关答案。

假设一个数组列表中有10000个数据,我想找到当前位于第5000个索引上的数字,数组列表如何知道这些索引并在恒定时间内给出结果?

因为如果我们遍历数组列表以查找数据,则将花费线性时间而不是恒定时间。

谢谢。

4 个答案:

答案 0 :(得分:4)

支持ArrayList的存储是一个数组。无论是存储原始值还是对象引用,数组中的所有对象在内存中都是连续的顺序。

对于数组访问,编译器所需要做的就是根据初始地址和所需索引(即O(1))计算正确的内存地址的指令。然后,它可以直接转到该计算出的地址。没有遍历,因此不是O(n)。

答案 1 :(得分:2)

ArrayList

ArrayList在引擎盖下使用了 array ,即名称。数组是具有直接,快速,基于索引的访问的数据结构。

因此,如果您要求索引为5 000的元素,则它只会询问其内部数组:

// More or less
return array[5000];

这是OpenJDK 8中的完整方法:

/**
 * 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);
}

尤其是,它不会不遍历到该点的所有元素。这就是其他没有基于索引的访问的数据结构所需要做的。如LinkedList。请注意,存在一个指示符界面,称为RandomAccessdocumentation)。实现该接口的类具有基于索引的直接访问。当前的实现是:

ArrayList, AttributeList, CopyOnWriteArrayList,
RoleList, RoleUnresolvedList, Stack, Vector

数组如何工作

那么,数组如何直接访问该元素?好吧,数组的大小是固定的。创建它时,需要告诉它大小。例如10 000

Foo[] array = new Foo[10000];

您的计算机将为10 000的{​​{1}}个对象分配连续内存。关键是存储区域是连续,而不是分散分布。因此,第三个元素紧随第二个元素之后,紧接在您的记忆中第四个元素之前。

当您现在要在位置Foo上检索元素时,计算机将在以下存储位置处检索5 000对象:

Foo

众所周知,自从声明数组以来,计算速度很快,显然是在恒定时间startAddressOfArray + 5000 * sizeOfFoo 中进行的。因此,数组可以直接基于索引访问其元素。因为这些东西存储在一起,所以连续地存储在内存中。

您可能会在Wikipedia上阅读有关数组的更多信息。

这是techcrashcourse.com的图片,显示了一个数组,其中包含每个元素的地址:

enter image description here

该数组的大小为O(1),并存储使用7个字节(2位)的整数。通常称为16,所以称为short数组。您可以看到每个元素与其上一个元素偏移new short[7]个字节(2的大小)。如图所示,这样可以通过简单的计算直接访问给定位置的元素。

答案 2 :(得分:1)

ArrayLists可以看作是一个对象数组(恰好正是它们的实现方式)。您可以像在O(1)上的任何其他数组一样对其进行索引。与真正的“数组”相比,它的优势在于,它可以跟踪“长度”,而与数组的长度无关,并在“溢出”时自动扩展数组,并执行一些额外的操作。

LinkedLists(可能是您正在考虑的结构)要求您从一个项目移到另一个项目,因此实现是O(n)在索引处查找项目。

答案 3 :(得分:0)

顾名思义,short将元素存储在数组中。这是oracle JDK中的相关代码:

ArrayList

因此,/** * The array buffer into which the elements of the ArrayList are stored. * The capacity of the ArrayList is the length of this array buffer. Any * empty ArrayList with elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA * will be expanded to DEFAULT_CAPACITY when the first element is added. */ transient Object[] elementData; // non-private to simplify nested class access 仅获得内部数组中的第n个元素,就不足为奇了:

list.get(index)