使用ArrayList时设置初始容量的重要性

简介: ArrayList是Java中比较常用的一个类,它是基于数组实现,非线程安全,可快速随机访问List中的元素。ArrayList具有动态扩容的机制,每次在添加元素时,都会判断容量是否够用,如果不够用,则需要扩容。

ArrayList是Java中比较常用的一个类,它是基于数组实现,非线程安全,可快速随机访问List中的元素。

ArrayList具有动态扩容的机制,每次在添加元素时,都会判断容量是否够用,如果不够用,则需要扩容。

JDK1.8中,ArrayList的初始容量为0,第一次添加元素时,会将容量设置为10,如果容量不够,则每次会扩大50%

扩容代码如下:

    /**
     * Increases the capacity to ensure that it can hold at least the
     * number of elements specified by the minimum capacity argument.
     *
     * @param minCapacity the desired minimum capacity
     */
    private void grow(int minCapacity) {
        // overflow-conscious code
        int oldCapacity = elementData.length;
        int newCapacity = oldCapacity + (oldCapacity >> 1);
        if (newCapacity - minCapacity < 0)
            newCapacity = minCapacity;
        if (newCapacity - MAX_ARRAY_SIZE > 0)
            newCapacity = hugeCapacity(minCapacity);
        // minCapacity is usually close to size, so this is a win:
        elementData = Arrays.copyOf(elementData, newCapacity);
    }

其中:

int newCapacity = oldCapacity + (oldCapacity >> 1);

容量被扩充为原容量的1.5倍,oldCapacity>>1,右移一位,即:oldCapacity除以2

elementData = Arrays.copyOf(elementData, newCapacity);

用Arrays的copyOf方法拷贝原数组内容,并设置新的长度。

可以看到ArrayList扩容需要做一次数组拷贝,如果是反复扩容,肯定会对程序的运行效率产生影响。所以在初始化ArrayList的时候,尽量设置初始化容量,避免其扩容。

测试代码:

        final int count = 20 * 100000;
        List<Integer> list = new ArrayList<>();
        long begin = System.currentTimeMillis();
        for(int i = 0; i < count ; i++) {
            list.add(i);
        }
        System.out.println("没有设置ArrayList初始容量: " + (System.currentTimeMillis() - begin) + " ms");
        
        list = new ArrayList<>(count);
        begin = System.currentTimeMillis();
        for(int i = 0; i < count ; i++) {
            list.add(i);
        }
        System.out.println("设置了ArrayList初始容量: " + (System.currentTimeMillis() - begin) + " ms");

执行结果:

没有设置ArrayList初始容量: 89 ms

设置了ArrayList初始容量: 18 ms

相关文章
|
数据采集 Java API
初识 DataHub|学习笔记
快速学习初识 DataHub
714 0
初识 DataHub|学习笔记
|
11月前
|
Java
深入探讨Java中的中断机制:INTERRUPTED和ISINTERRUPTED方法详解
在Java多线程编程中,中断机制是协调线程行为的重要手段。了解和正确使用中断机制对于编写高效、可靠的并发程序至关重要。本文将深入探讨Java中的`Thread.interrupted()`和`Thread.isInterrupted()`方法的区别及其应用场景。
283 4
|
人工智能 前端开发 搜索推荐
|
JavaScript API 网络架构
vue 动态路由使用
【8月更文挑战第30天】vue 动态路由使用
222 0
|
缓存 Java 大数据
深入解析JVM调优:解决OutOfMemoryError、内存泄露、线程死锁、锁争用和高CPU消耗问题
深入解析JVM调优:解决OutOfMemoryError、内存泄露、线程死锁、锁争用和高CPU消耗问题
530 0
|
Oracle 关系型数据库 数据库
|
消息中间件 Kafka
Kafka单机模式和集群模式环境搭建
Kafka单机模式和集群模式环境搭建
98 0
|
监控
实践解读CLOSE_WAIT和TIME_WAIT
实践解读CLOSE_WAIT和TIME_WAIT
517 0
实践解读CLOSE_WAIT和TIME_WAIT
|
运维 NoSQL 安全
图解MongoDB数据库学习路线指南
文章目录 1、MongoDB数据库学习大纲 2、MongoDB数据格式 3、MongoDB数据库特点 4、MongoDB数据库应用场景 5、MongoDB数据库单节点部署 5、MongoDB数据库常用操作指令 6、MongoDB数据库增删改查数据查询 7、MongoDB数据库运维工具 8、MongoDB授权登陆安全模式 9、MongoDB副本集集群 10、MongoDB数据备份恢复机制 11.MongoDB数据误删除恢复流程
709 0
图解MongoDB数据库学习路线指南
|
Java 测试技术 API
Java 中拼接 String 的 N 种方式
Java 中拼接 String 的 N 种方式
609 0
Java 中拼接 String 的 N 种方式