Java——LinkedList 和 ArrayList的全面对比讲解

LinkedListArrayList 的全面对比讲解 📚:


1. 数据结构的不同🛠️

  • LinkedList:它基于双向链表。每个元素(我们叫它节点)不仅存储数据,还存储了指向前后元素的两个指针🔗。这就像是一列火车🚂,每节车厢都知道自己前后是哪节车厢。

    生活例子🍔:假如你正在排队买奶茶🥤。你前后都有一个人,想插队的话,你只需要拉住你前面和后面的人,让他们也拉住你。你可以很快插入队伍,因为你只需要跟两个人沟通(前后两个人)。同样,删除也是一样的简单😉。

  • ArrayList:它基于动态数组。这意味着它需要一段连续的内存来存储数据📦,而不是像LinkedList那样通过指针相互连接。每个元素都通过索引快速访问,就像一排整齐的盒子📦📦📦。

    生活例子🍰:想象你在超市购物🛒,推着购物车走过货架📑。每个商品都有固定的编号🏷️(索引),你只需要找到相应编号的货架,就可以快速拿到商品。这是因为所有商品都整齐排列在货架上,不用一个个看过去。


2. 访问速度(随机访问)🏃‍♀️💨

  • LinkedList:因为数据是通过链表存储的,要访问某个特定位置的元素,你需要从头(或尾)开始,逐个走过每个节点才能找到目标⚙️。这个过程就像翻找一个很长的链子,一环一环地往下走🔗,所以速度会很慢。

    生活例子🍔:想象你有一串钥匙🔑,但你想要找到其中的第10把钥匙。你得从第1把开始一把一把数过去,直到找到第10把。这就是LinkedList的访问方式,比较费时⏳。

  • ArrayList:因为数组是连续存储的,所有元素的内存地址是连续的。所以,你可以直接通过索引来快速访问某个元素🏃‍♂️,就像有一份清单📑,上面标明了每个商品在超市里的具体位置。

    生活例子🍰:还记得我们在超市找商品的例子吗?你只需要找到货架编号,就能直接快速拿到商品🏷️。这就是ArrayList访问的方式,速度非常快⚡。


3. 插入和删除操作的不同🔄

  • LinkedList:因为它是链表结构,插入和删除操作非常方便,特别是在头部或尾部插入和删除元素的时候。你只需要调整前后节点的指针指向,几乎不会影响其他节点🛠️。然而,如果你想在中间位置进行操作,你还得先从头开始找这个位置⚙️。

    生活例子🍔:比如你想在排队时插队,或者你排到一半突然不想买奶茶了🍹,离开队伍。因为你只需要拉住你前面和后面的人,告诉他们换一下顺序,所以插入和删除非常方便,效率高🏆。

  • ArrayList:在末尾插入是比较快的,因为只需要将新元素放在最后一个位置📦。但是如果你想在中间插入或删除元素,所有后面的元素都要往前或往后移位。这就像你在一排整齐的盒子里中途插入一个新盒子📦,你不得不移动很多其他盒子才能腾出空间。

    生活例子🍰:想象你在超市的货架中间突然想加一个新商品,你必须把后面的商品全都挪开才能腾出空位😵。所以在中间插入和删除的成本比较高。


4. 内存占用情况📏

  • LinkedList:由于每个节点除了存储数据外,还要存储指向前后节点的两个指针🧷,所以相比ArrayList,它占用的内存更多📊。

    生活例子🍔:就像每个人手里都拿着两根绳子,一根拉住前面的人,一根拉住后面的人。每个人不仅要站着,还得多占点地方拉绳子,所以会比直接排好队的ArrayList占用更多空间🪢。

  • ArrayList:它只需要存储数据本身,没有额外的指针开销。虽然在增长时可能需要重新分配内存空间,但通常内存占用相对较少📉。

    生活例子🍰:ArrayList就像是一个紧凑的货架,所有商品整齐排列,没有多余的“拉绳子”的动作,所以它更加节省空间💡。


5. 性能和使用场景💼

  • LinkedList:适用于需要频繁插入和删除元素的场景,尤其是在队列的头部和尾部操作时⏩。比如:当你需要模拟一列排队系统时👥,LinkedList非常合适。
  • ArrayList:适用于快速访问数据的场景,尤其是频繁通过索引来读取数据的情况📑。如果你经常要遍历和访问元素,比如展示商品列表🛒,ArrayList会表现得更好。

总结大比拼🏆:

特性LinkedListArrayList
数据结构基于双向链表,节点包含数据和指针🔗基于动态数组,数据连续存储📦
随机访问速度慢,需要遍历节点🔗快,可以通过索引直接访问⚡
插入和删除头尾操作快,尤其是插入/删除时效率高⏩末尾操作快,但在中间插入/删除时需要移动大量数据📦📦📦
内存占用占用内存较多,因为每个节点都有两个额外的指针🔗占用内存较少,只存储数据本身📉
适用场景适合需要频繁插入/删除的场景,如队列👥适合需要快速访问数据的场景,如商品列表🛒

在 LinkedList 和 ArrayList 中插入元素的性能比较📝

这部分代码会对比在 LinkedListArrayList 中插入元素的效率。在这个例子中,我们向列表中插入 100000 个元素,看看它们的表现。

 
import java.util.ArrayList;
import java.util.LinkedList;

public class InsertComparison {
    public static void main(String[] args) {
        // 创建 LinkedList 和 ArrayList
        LinkedList<String> linkedList = new LinkedList<>();
        ArrayList<String> arrayList = new ArrayList<>();
        
        // 插入 100000 个元素到 LinkedList
        long linkedListStartTime = System.nanoTime(); // 记录开始时间
        for (int i = 0; i < 100000; i++) {
            linkedList.add("Element " + i); // 向 LinkedList 中添加元素
        }
        long linkedListEndTime = System.nanoTime(); // 记录结束时间
        System.out.println("LinkedList 插入 100000 个元素花费的时间: " + (linkedListEndTime - linkedListStartTime) + " 纳秒");

        // 插入 100000 个元素到 ArrayList
        long arrayListStartTime = System.nanoTime(); // 记录开始时间
        for (int i = 0; i < 100000; i++) {
            arrayList.add("Element " + i); // 向 ArrayList 中添加元素
        }
        long arrayListEndTime = System.nanoTime(); // 记录结束时间
        System.out.println("ArrayList 插入 100000 个元素花费的时间: " + (arrayListEndTime - arrayListStartTime) + " 纳秒");
    }
}

解释💡:

  • LinkedList 在插入时,特别是在尾部插入,表现会不错,因为它不需要移动其他元素,只是修改指针🔗。
  • ArrayList 在插入时,尤其是在末尾插入,也表现得很好,但如果容量不足时,它需要重新扩展数组📦,所以在某些情况下可能会变慢。

2. 在 LinkedList 和 ArrayList 中访问元素的性能比较📝

这部分代码对比了 LinkedListArrayList访问元素时的性能。我们尝试获取第 50000 个元素,看看它们的表现如何。

 
import java.util.ArrayList;
import java.util.LinkedList;

public class AccessComparison {
    public static void main(String[] args) {
        // 创建并填充 LinkedList 和 ArrayList
        LinkedList<String> linkedList = new LinkedList<>();
        ArrayList<String> arrayList = new ArrayList<>();
        for (int i = 0; i < 100000; i++) {
            linkedList.add("Element " + i);
            arrayList.add("Element " + i);
        }

        // 访问 LinkedList 的第 50000 个元素
        long linkedListStartTime = System.nanoTime();
        String linkedListElement = linkedList.get(50000);
        long linkedListEndTime = System.nanoTime();
        System.out.println("LinkedList 访问第 50000 个元素花费的时间: " + (linkedListEndTime - linkedListStartTime) + " 纳秒");

        // 访问 ArrayList 的第 50000 个元素
        long arrayListStartTime = System.nanoTime();
        String arrayListElement = arrayList.get(50000);
        long arrayListEndTime = System.nanoTime();
        System.out.println("ArrayList 访问第 50000 个元素花费的时间: " + (arrayListEndTime - arrayListStartTime) + " 纳秒");
    }
}

解释💡:

  • LinkedList 需要从头(或尾)开始逐个查找元素,因为它是链表结构🔗,所以访问速度相对慢一些⏳。
  • ArrayList 可以通过索引直接访问元素📑,因此访问速度非常快⚡。

3. 在 LinkedList 和 ArrayList 中在开头插入元素的性能比较📝

这一部分代码对比了在 LinkedListArrayList头部插入操作。我们在开头插入一个新元素,看看性能差异。

 
import java.util.ArrayList;
import java.util.LinkedList;

public class HeadInsertComparison {
    public static void main(String[] args) {
        // 创建并填充 LinkedList 和 ArrayList
        LinkedList<String> linkedList = new LinkedList<>();
        ArrayList<String> arrayList = new ArrayList<>();
        for (int i = 0; i < 100000; i++) {
            linkedList.add("Element " + i);
            arrayList.add("Element " + i);
        }

        // 在 LinkedList 的开头插入元素
        long linkedListStartTime = System.nanoTime();
        linkedList.add(0, "New Element");
        long linkedListEndTime = System.nanoTime();
        System.out.println("LinkedList 在开头插入元素花费的时间: " + (linkedListEndTime - linkedListStartTime) + " 纳秒");

        // 在 ArrayList 的开头插入元素
        long arrayListStartTime = System.nanoTime();
        arrayList.add(0, "New Element");
        long arrayListEndTime = System.nanoTime();
        System.out.println("ArrayList 在开头插入元素花费的时间: " + (arrayListEndTime - arrayListStartTime) + " 纳秒");
    }
}

解释💡:

  • LinkedList 只需要调整头部节点的指针🔗,所以在头部插入元素非常快⏩。
  • ArrayList 则需要移动所有元素📦,所以在头部插入元素时会很慢😵。

总结大比拼🏆:

  • 插入性能:LinkedList 在头尾插入时表现优异,而 ArrayList 只在末尾插入时表现好。
  • 访问性能:ArrayList 的访问速度比 LinkedList 快很多,尤其是在随机访问的情况下。
  • 内存占用:LinkedList 由于存储了前后两个指针,占用更多内存;ArrayList 内存占用较少,但可能需要扩展数组。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值