首页 > 编程语言 >Java面试要点49 - Java ArrayList与LinkedList性能对比

Java面试要点49 - Java ArrayList与LinkedList性能对比

时间:2024-11-30 22:29:04浏览次数:7  
标签:Java LinkedList 49 ArrayList 性能 add arrayList public

在这里插入图片描述

文章目录


一、引入

在Java程序开发过程中,合理选择集合类对于程序性能的影响至关重要。ArrayList和LinkedList作为Java中最常用的两种List实现,它们都能存储和管理数据,但由于底层实现方式的不同,在不同场景下的性能表现也大相径庭。

二、底层结构对比

2.1 ArrayList的实现原理

ArrayList的底层是基于数组实现的。当创建一个ArrayList时,实际上是在内存中分配了一个连续的Object数组。这种结构的特点是可以通过索引快速访问任意位置的元素,但在需要动态调整大小时,需要创建新数组并复制数据。我们来看一个简单的示例:

//创建一个ArrayList并观察其内部结构
ArrayList<String> arrayList = new ArrayList<>();
//添加元素时,如果超出当前容量会触发扩容
arrayList.add("Java");
arrayList.add("Python");
arrayList.add("JavaScript");

//获取ArrayList的实际大小
int size = arrayList.size();          //返回3
//获取内部数组的长度(默认初始容量为10)
//这部分代码仅用于演示,实际项目中不建议这样使用反射
Field field = ArrayList.class.getDeclaredField("elementData");
field.setAccessible(true);
Object[] elementData = (Object[]) field.get(arrayList);
int capacity = elementData.length;    //返回10

2.2 LinkedList的实现原理

LinkedList采用双向链表实现,每个节点都包含了前后节点的引用。这种结构使得插入和删除操作只需要修改相关节点的引用即可完成。

以下是LinkedList节点结构的示意代码:

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;
    }
}

三、性能测试实战

3.1 测试代码实现

通过一个完整的性能测试程序来直观地展示两种集合类在不同操作下的性能差异:

import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;
import java.util.Random;

public class ListPerformanceComparison {
    private static final int OPERATION_COUNT = 100000;
    private static final Random random = new Random();

    public static void main(String[] args) {
        // 初始化测试数据
        ArrayList<Integer> arrayList = new ArrayList<>();
        LinkedList<Integer> linkedList = new LinkedList<>();
        
        // 测试1: 顺序添加元素
        long startTime = System.nanoTime();
        for (int i = 0; i < OPERATION_COUNT; i++) {
            arrayList.add(i);
        }
        long arrayListAddTime = System.nanoTime() - startTime;
        
        startTime = System.nanoTime();
        for (int i = 0; i < OPERATION_COUNT; i++) {
            linkedList.add(i);
        }
        long linkedListAddTime = System.nanoTime() - startTime;
        
        System.out.println("顺序添加性能对比:");
        System.out.printf("ArrayList: %d ms%n", arrayListAddTime / 1_000_000);
        System.out.printf("LinkedList: %d ms%n", linkedListAddTime / 1_000_000);
    }
}

四、性能特征分析

4.1 顺序添加性能

在顺序添加场景下,ArrayList的性能略优于LinkedList。这是因为ArrayList只需要将元素追加到数组末尾,而LinkedList需要创建新的节点对象并建立引用关系。

下面是一个实际场景的代码示例:

public void bulkDataProcessing() {
    List<String> dataList = new ArrayList<>();  //选择ArrayList
    for (int i = 0; i < 1000000; i++) {
        dataList.add("数据" + i);    //顺序添加,ArrayList性能更好
    }
}

4.2 随机访问性能

ArrayList在随机访问时表现出色,因为它可以直接通过数组索引访问元素。而LinkedList在随机访问时需要从头或尾遍历链表,性能相对较差。这个特性在大量随机访问操作时尤为明显。

五、实际应用场景示例

5.1 数据缓存实现

public class DataCache {
    private List<String> cache;
    
    public DataCache() {
        cache = new ArrayList<>(1000);  // 预分配容量
    }
    
    public String get(int index) {
        return cache.get(index);  // O(1)的访问性能
    }
}

5.2 消息队列实现

public class MessageQueue {
    private List<String> queue;
    
    public MessageQueue() {
        queue = new LinkedList<>();
    }
    
    public void addMessage(String message) {
        queue.add(message);       // 在尾部添加
    }
    
    public String processNext() {
        return ((LinkedList<String>)queue).pollFirst();  // 从头部移除
    }
}

六、总结

通过本文的分析和实战示例,深入理解了ArrayList和LinkedList在不同场景下的性能特征。ArrayList凭借其连续的内存布局和直接索引访问的特性,在随机访问和顺序添加操作中表现出色,特别适合于那些需要频繁随机访问和较少修改的场景。而LinkedList由于其链表结构的特点,在频繁的插入删除操作中具有明显优势,尤其适合实现队列、栈等数据结构。

在实际开发中,需要根据具体的使用场景和操作特点来选择合适的集合类型。同时还要注意一些性能优化的细节,比如为ArrayList预分配合适的初始容量,以及在LinkedList中避免过多的随机访问操作。

标签:Java,LinkedList,49,ArrayList,性能,add,arrayList,public
From: https://blog.csdn.net/weixin_55344375/article/details/144029089

相关文章

  • Java面试要点50 - List的线程安全实现:CopyOnWriteArrayList
    文章目录一、引入二、实现原理解析2.1写时复制机制2.2读写分离策略三、性能测试分析四、应用场景分析4.1事件监听器管理4.2缓存实现五、最佳实践建议5.1性能优化技巧5.2常见陷阱规避总结一、引入在并发编程中,线程安全的集合类扮演着重要角色。CopyOnWri......
  • Java日志手机号脱敏工具类
    背景在开发过程中,很容易将用户敏感信息,例如手机号码、身份证等,打印在日志平台。为了保护用户数据,又不影响日志的打印,需要将日志中的敏感信息进行脱敏。效果没看明白,强烈建议pull项目,执行一下项目中SensitiveUtils#main方法。特性支持多层级Json/对象字段脱敏支持一次......
  • Java常见的锁策略
    目录Java常见的锁策略悲观锁和乐观锁轻量级锁和重量级锁自旋锁和挂起等待锁普通互斥锁和读写锁公平锁和非公平锁可重入锁和不可重入锁Java中的synchronized算哪种情况?系统原生的锁算哪种情况?synchronized的加锁过程,尤其是“自适应”是咋回事?synchronized中内置的优化策略......
  • 力扣--LCR 149.彩灯装饰记录I
    题目代码/**Definitionforabinarytreenode.publicclassTreeNode{intval;TreeNodeleft;TreeNoderight;TreeNode(){}TreeNode(intval){this.val=val;}TreeNode(intval,TreeNodeleft,TreeNoderight){this.val=val;......
  • ssm基于Java的高校教学业绩信息管理系统(10279)
     有需要的同学,源代码和配套文档领取,加文章最下方的名片哦一、项目演示项目演示视频二、资料介绍完整源代码(前后端源代码+SQL脚本)配套文档(LW+PPT+开题报告)远程调试控屏包运行三、技术介绍Java语言SSM框架SpringBoot框架Vue框架JSP页面Mysql数据库IDEA/Eclipse开发四、项......
  • Java 数据脱敏?别慌,掩护队已经上线!
    引言大家好!今天我们要聊一聊数据脱敏。这个词听起来像特工电影里的高科技武器,其实它就是给敏感数据穿上“伪装衣”,防止“坏人”偷窥。无论是银行账号、身份证号码、邮箱地址,这些信息都需要时刻保持低调。如何低调?没错——数据脱敏,Java已准备好为你服务!1.什么是数据脱敏?......
  • 《Django 5 By Example》阅读笔记:p455-p492
    《Django5ByExample》学习第16天,p455-p492总结,总计38页。一、技术总结1.myshop(1)打折功能使用折扣码实现,但是折扣码是手动生成的,感觉实际业务中应该不是这样的。(2)推荐功能使用Redis做缓存,结合商品的销量做推荐,算是一种普通的实现方案。二、英语总结(生词:2)1.......
  • 从高校就业信息管理系统到Python和Java类系统开题报告:结构化研究的提纲优化
    个人名片......
  • 大学生HTML期末大作业——HTML+CSS+JavaScript培训机构(画室)
    HTML+CSS+JS【培训机构】网页设计期末课程大作业web前端开发技术web课程设计网页规划与设计......
  • JavaWeb:Servlet (学习笔记)【1】
    目录一,Servlet介绍1,简介2,Servlet技术特点3,Servlet在应用程序中的位置4,Servlet在程序中到底处于一个什么地位?二,servlet运行过程:三,servlet路径配置四,Servlet的生命周期1,伪单例模式2,生命周期的步骤3,讲解Servlet是一个伪单例模式五,什么是生命周期啊?就是说什么时候有......