ArrayList与LinkedList获取指定元素对比(源码分析)

简介: ArrayList与LinkedList获取指定元素对比(源码分析)

ArrayList与LinkedList获取指定元素对比(源码分析)


ArrayList获取指定元素

  1. 首先在主函数中使用ArrayList生成一个size为一千万的List实例list
int max = 10000000;
List<String> list = new ArrayList<>(max);
for (int i = 0; i < max; i++) {
    list.add("a");
}
/**
 * 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);
}


可以看到,首先使用rangeCheck对index进行检验;然后点进去elementData:

@SuppressWarnings("unchecked")
E elementData(int index) {
    return (E) elementData[index];
}
  1. 发现直接返回了elementData数组中下标为index的元素,时间复杂度为O(1)
  2. 测试一下使用get方法来获取最后一个元素所需的时间:
long startTime = System.currentTimeMillis();
list.get(max - 1).hashCode();
long endTime = System.currentTimeMillis();
System.out.println("ArrayList获取最后一个元素所需时间: "+(endTime - startTime));

运行结果如下:

ArrayList获取最后一个元素所需时间: 0
  1. 发现该方法运行时间几乎为0,因为无需遍历元素,直接根据index返回数据即可;

LinkedList获取指定元素

  1. 首先在主函数中使用LinkedList生成一个size为一千万的List实例list
int max = 10000000;
List<String> list = new LinkedList<>();
for (int i = 0; i < max; i++) {
    list.add("a");
}


来看一下LinkedListget方法的源码:

/**
 * 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) {
    checkElementIndex(index);
    return node(index).item;
}


可以看到,首先使用checkElementIndexindex进行检验;然后点进去node

/**
 * Returns the (non-null) Node at the specified element index.
 */
Node<E> node(int index) {
    // assert isElementIndex(index);
    if (index < (size >> 1)) {
        Node<E> x = first;
        for (int i = 0; i < index; i++)
            x = x.next;
        return x;
    } else {
        Node<E> x = last;
        for (int i = size - 1; i > index; i--)
            x = x.prev;
        return x;
    }
}
  1. 可以看出,当index位于size的前一半时,从前往后去遍历元素;当index位于size的后一半时,从后往前去遍历元素;所以当index恰好位于中间位置时,所需时间最长;
  2. 测试一下使用get方法来获取中间元素所需的时间:
long startTime = System.currentTimeMillis();
list.get(max / 2).hashCode();
long endTime = System.currentTimeMillis();
System.out.println("LinkedList获取中间元素所需时间: "+(endTime - startTime));


运行结果如下:

LinkedList获取中间元素所需时间: 17

发现该方法运行时间较长,因为需要遍历元素去寻找数据;


结论

  1. 对于需要经常查询元素的场景,应尽量使用ArrayList来实现,所需时间复杂度为O(1)
目录
相关文章
|
安全 编译器 C语言
深入理解C/C++预处理器指令#pragma once以及与ifndef的比较
深入理解C/C++预处理器指令#pragma once以及与ifndef的比较
958 0
|
消息中间件 存储 缓存
Kafka 架构和原理机制 (图文全面详解)
一文了解掌握 Kafka 的基本架构、原理、特性、应用场景,以及Zookeeper 在 kafka 的作用。
Kafka 架构和原理机制 (图文全面详解)
|
9月前
|
Devops Java 应用服务中间件
你们团队的规范吃灰去了吗,如何落地团队规范?
本文探讨了项目团队中常见的沟通问题及其解决方案。通过制定统一的规范,可以降低沟通成本,提高团队效率。然而,规范的落地成为新的挑战。借助自动化工具和平台,如DevOps工具链,可以有效解决这一问题。文中介绍了几种主要的DevOps工具及其应用场景,帮助团队实现高效协作。
126 0
|
Java 应用服务中间件 数据库连接
ssm项目整合,简单的用户管理系统
文章介绍了一个使用SSM框架(Spring、SpringMVC、MyBatis)构建的简单用户管理系统的整合过程,包括项目搭建、数据库配置、各层代码实现以及视图展示。
ssm项目整合,简单的用户管理系统
|
存储 Linux Shell
常用vim命令和vim基本使用及Linux用户的管理,用户和组相关文件
这篇文章介绍了Vim编辑器的基本使用、常用命令和模式,以及Linux系统中用户和组的管理方法,包括用户和组相关文件如/etc/passwd、/etc/shadow和/etc/group的说明。
常用vim命令和vim基本使用及Linux用户的管理,用户和组相关文件
|
数据安全/隐私保护
PyQt5-Qt Designer控件之间的伙伴关系和Tab顺序如何设置?
PyQt5-Qt Designer控件之间的伙伴关系和Tab顺序如何设置?
286 0
PyQt5-Qt Designer控件之间的伙伴关系和Tab顺序如何设置?
|
C++ 存储 容器
Qt QList类和QLinkedList类 详解
Qt QList类和QLinkedList类 详解
|
编译器 API C语言
在x86架构汇编语言中函数参数传递的三种约定
在x86架构汇编语言中函数参数传递的三种约定
554 2
|
编译器 C语言 C++
C/C++编译优化技巧:预编译头文件(PCH)使用方法
C/C++编译优化技巧:预编译头文件(PCH)使用方法
1356 1
|
数据采集 机器学习/深度学习 Python
在Python中进行特征编码
在Python中进行特征编码
256 1