java的ArrayList(线性表)和LinkedList(双向链表)的深入学习

news/2024/7/18 22:17:45

java的ArrayList和LinkedList的实现原理是完全不一样的,一个是用数组,而另一个则是用节点(Node)。

我们经常说,如果查询多,那就用ArrayList,而如果删除或者添加,那就用LinkedList。为什么要这样子,他们两者之间的区别又是怎样的,而今天我们就要从源码来分析他们

①先看看ArrayList和LinkedList他们的结构

ArrayList:一个Object数组

/**
     * 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

 LinkedList:一个Node对象

private static class Node<E> {
        E item;
        Node<E> next;
        Node<E> prev;

        Node(Node<E> prev, E element, Node<E> next) {
            this.item = element;
            this.next = next;
            this.prev = prev;
        }
    }

②他们之间获取元素方法之间的不同,我们来看看get方法

ArrayList:

/**
     * 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);
    }
@SuppressWarnings("unchecked")
    E elementData(int index) {
        return (E) elementData[index];
    }

从这里我们可以看到,ArrayList通过索引即可从数组里面直接获取,时间复杂度为O(1)

LinkedList:

/**
     * 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);//同样也是检查索引是否大于LinkedList的长度
        return node(index).item;
    }
/**
     * 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;
        }
    }

因为我们知道的元素只有first和last,所以这里只用了一次二分法,如果index小于size/2,那么就first开始查找,一直从0遍历到index。同理如果index大于size/2,那么就last倒过来查找,一直从size-1遍历到index。时间复杂度为O(n/2)

总结:ArrayList比LinkedList的查找效率要高。

②他们之间获取元素方法之间的不同,我们来看看remove方法

ArrayList:

    /**
     * Removes the element at the specified position in this list.
     * Shifts any subsequent elements to the left (subtracts one from their
     * indices).
     *
     * @param index the index of the element to be removed
     * @return the element that was removed from the list
     * @throws IndexOutOfBoundsException {@inheritDoc}
     */
    public E remove(int index) {
        rangeCheck(index);//同样检查索引

        modCount++;
        E oldValue = elementData(index);

        int numMoved = size - index - 1;
        if (numMoved > 0)
            System.arraycopy(elementData, index+1, elementData, index,
                             numMoved);
        elementData[--size] = null; // clear to let GC do its work

        return oldValue;
    }

在这里我要说一下System.arraycopy(src, srcPos, dest, destPos, length),这是一个复制数组的方法,其中:

src:数据源,也就是将要被复制的数组

srcPos:数据源的某个索引,也就是将从数据源那个所以开始复制

dest:目标源,将要复制到的数组

destPos:目标源的某个索引,也是就是复制从目标源的destPos开始

length:复制的长度,也就是将将数据源的srcPos到srcPos+length复制到目标源的destPos到destPos到destPos+length

这么说,我相信大家上面的那段代码能看懂了

由于System.arraycopy的方法是native的,所以就不贴出来给大家看了,但我个人猜想里面肯定少不了遍历,才能将数组复制,所以我这里给它的时间复杂度是O(n)

LinkedList:

/**
     * Removes the element at the specified position in this list.  Shifts any
     * subsequent elements to the left (subtracts one from their indices).
     * Returns the element that was removed from the list.
     *
     * @param index the index of the element to be removed
     * @return the element previously at the specified position
     * @throws IndexOutOfBoundsException {@inheritDoc}
     */
    public E remove(int index) {
        checkElementIndex(index);//检查索引是否越界
        return unlink(node(index));
    }
E unlink(Node<E> x) {
        // assert x != null;
        final E element = x.item;
        final Node<E> next = x.next;
        final Node<E> prev = x.prev;

        if (prev == null) {
            first = next;
        } else {
            prev.next = next;
            x.prev = null;
        }

        if (next == null) {
            last = prev;
        } else {
            next.prev = prev;
            x.next = null;
        }

        x.item = null;
        size--;
        modCount++;
        return element;
    }

这里unlink里面的操作就只是做了将要删除的元素的上一个元素和将要删除的元素的下一个元素连起来,而主要消耗资源的还是node(index),根据所以获取元素,这个在①里面已经说到了,所以时间复杂度为O(n/2)

总结:LinkedList比ArrayList的查找效率要高。

③至于添加,大家可以自己去看一下,实际上是跟②差不多

转载于:https://www.cnblogs.com/pig-brother/p/7347499.html


http://www.niftyadmin.cn/n/3122528.html

相关文章

完全数java

完全数&#xff1a;小于本身的所有因子的和&#xff08;包括1&#xff09; public class test01 {public static void main(String[] args) {Scanner scannernew Scanner(System.in);int nscanner.nextInt();for (int i2;i<n;i){int sum0;for (int j1;j<i;j)if (i%j0) su…

[Hihocoder] 字符串排序

题目 http://hihocoder.com/problemset/problem/1712 题解 https://www.zybuluo.com/wsndy-xx/note/1135606转载于:https://www.cnblogs.com/shandongs1/p/8992290.html

C#-WebForm-★★★JQuery知识——DOM操作★★★

例如&#xff1a; $("#btn1").attr( "disabled" , "disabled" ); 例如&#xff1a; $("#d1").css( "width" , "100px" );  设置宽度为100px 例如&#xff1a; 获取<input type"text" id"txt…

mysql-5.7.15-winx64配置

1. 配置环境变量 1.1 添加path路径 选择 控制面板>系统和安全>系统>高级系统设置>环境变量 mysql文件目录的绝对路径\bin 1.2 修改mysql default.ini 配置文件 2. 以管理员身份进入命令行cmd 进入mysql的bin目录下 3. mysqld --initialize-insecure &am…

圆 最小外包矩形_点圆最值母子相似阿斯圆

转发或点击文章末“在看”也是一种“点赞”如下图&#xff0c;OP、OA线段长度不变&#xff0c;看到这幅动态图&#xff0c;你能想到什么&#xff1f;1、当点P运动到C点时&#xff0c;AP达到最大值。2、当点P运动到B点时&#xff0c;AP达到最小值。3、在运动过程中&#xff0c;O…

CentOS6.8下安装MySQL5.6

一&#xff1a;卸载旧版本 使用下面的命令检查是否安装有MySQL Server rpm -qa | grep mysql有的话通过下面的命令来卸载掉 rpm -e mysql       //普通删除模式 rpm -e --nodeps mysql // 强力删除模式&#xff0c;如果使用上面命令删除时&#xff0c;提示有…

实现单行或多行文本溢出显示省略号

如果实现单行文本的溢出显示省略号同学们应该都知道用text-overflow:ellipsis属性来&#xff0c;当然还需要加宽度width属来兼容部分浏览。 实现代码&#xff1a; overflow: hidden; text-overflow:ellipsis; white-space: nowrap; 效果&#xff1a; 但是这个属性只支持单行文本…

SVM基础知识

别人的资料 解密SVM系列&#xff08;一&#xff09;&#xff1a;关于拉格朗日乘子法和KKT条件解密SVM系列&#xff08;二&#xff09;&#xff1a;SVM的理论基础解密SVM系列&#xff08;三&#xff09;&#xff1a;SMO算法原理与实战求解解密SVM系列&#xff08;四&#xff09;…