ArrayList 和 Array区别

ArrayListArray 都用于存储元素,但它们的实现和行为有很多不同。以下是这两者的详细对比和区别:

1. 存储方式

  • Array(数组):数组是 Java 中最基本的数据结构,用于存储一组相同类型的元素。数组的大小在创建时确定,且大小不可改变。

    int[] array = new int[5];  // 创建一个固定大小为 5 的数组
    
  • ArrayListArrayList 是基于数组的动态集合类,大小是可变的。ArrayList 内部使用数组来存储元素,但在元素增加时会自动扩展数组的大小。

    ArrayList<Integer> arrayList = new ArrayList<>();  // 创建一个空的 ArrayList
    

2. 固定大小 vs 动态大小

  • Array(数组):数组的大小在创建时决定,一旦设置后,数组的大小无法改变。如果需要更大的数组,必须创建一个新的数组并复制元素。

    int[] array = new int[3];  // 数组大小为 3
    array = new int[5];  // 重新创建一个更大的数组
    
  • ArrayListArrayList 的大小是动态的,当元素数量超过当前数组的容量时,ArrayList 会自动扩容,通常扩容为原容量的 1.5 倍。

    ArrayList<Integer> list = new ArrayList<>();
    list.add(1);
    list.add(2);  // 可以动态增加元素,ArrayList 会自动扩容
    

3. 类型

  • Array(数组):数组是一个基本的数据结构,支持基本数据类型(如 int, char 等)以及对象类型。

    int[] arr1 = new int[3];  // 存储基本类型
    String[] arr2 = new String[3];  // 存储对象类型
    
  • ArrayListArrayList 只能存储对象(如 Integer, String 等),不能直接存储基本数据类型。如果需要存储基本数据类型,可以使用其包装类(如 Integer, Double 等)。

    ArrayList<Integer> list = new ArrayList<>();  // 存储对象类型
    

4. 访问元素的方式

  • Array(数组):通过索引访问数组中的元素,支持快速随机访问(O(1) 时间复杂度)。

    int[] arr = {1, 2, 3};
    System.out.println(arr[1]);  // 输出 2
    
  • ArrayListArrayList 也通过索引访问元素,访问时间同样是 O(1),但它内部是通过方法调用来访问元素。

    ArrayList<Integer> list = new ArrayList<>();
    list.add(1);
    list.add(2);
    System.out.println(list.get(1));  // 输出 2
    

5. 插入和删除元素

  • Array(数组):数组大小是固定的,插入和删除元素较为麻烦。如果需要增加或删除元素,必须手动移动元素或者创建一个新的数组。

    int[] arr = {1, 2, 3};
    arr[1] = 5;  // 可以直接修改元素
    
  • ArrayListArrayList 支持动态插入和删除元素,插入和删除元素时,ArrayList 会自动扩展或收缩,并且内部会处理元素的移动。

    ArrayList<Integer> list = new ArrayList<>();
    list.add(1);
    list.add(2);
    list.add(1, 3);  // 在索引 1 位置插入 3
    list.remove(0);  // 删除索引 0 位置的元素
    

6. 性能

  • Array(数组):由于数组的大小是固定的,且直接在内存中存储,访问速度非常快。对数组的读取和写入操作的时间复杂度为 O(1)。

  • ArrayListArrayList 的插入和删除操作会导致数组的重新分配(当数组容量不足时)。因此,插入和删除元素的性能相对较差,尤其是在数组的中间位置。扩容操作可能导致性能下降。

    ArrayList<Integer> list = new ArrayList<>();
    for (int i = 0; i < 1000; i++) {
        list.add(i);  // 插入元素,可能会触发扩容
    }
    

7. 内存管理

  • Array(数组):数组的内存分配是静态的,即数组创建时需要指定大小,这会消耗一块固定的内存区域。

  • ArrayListArrayList 会根据需要动态分配内存,在扩容时,ArrayList 会创建一个新的更大的数组,并将原数组的元素复制到新数组中。这个过程会消耗更多的内存。

8. 常见操作性能

操作 Array(数组) ArrayList
访问元素(通过索引) O(1) O(1)
插入元素(末尾) O(1)(前提是数组容量足够) 平均 O(1),但可能需要扩容
插入元素(中间) O(n)(需要移动元素) O(n)(需要移动元素)
删除元素(末尾) O(1) O(1)(除非需要扩容)
删除元素(中间) O(n)(需要移动元素) O(n)(需要移动元素)

9. 代码示例

Array(数组)使用示例:

public class ArrayExample {
    public static void main(String[] args) {
        int[] arr = new int[5];  // 创建一个大小为 5 的数组
        arr[0] = 1;
        arr[1] = 2;
        arr[2] = 3;
        arr[3] = 4;
        arr[4] = 5;

        // 访问元素
        System.out.println(arr[2]);  // 输出 3

        // 修改元素
        arr[2] = 10;
        System.out.println(arr[2]);  // 输出 10
    }
}

ArrayList 使用示例:

import java.util.*;

public class ArrayListExample {
    public static void main(String[] args) {
        ArrayList<Integer> list = new ArrayList<>();  // 创建一个空的 ArrayList
        list.add(1);
        list.add(2);
        list.add(3);

        // 访问元素
        System.out.println(list.get(1));  // 输出 2

        // 修改元素
        list.set(1, 10);
        System.out.println(list.get(1));  // 输出 10

        // 插入元素
        list.add(1, 5);  // 在索引 1 位置插入 5
        System.out.println(list);  // 输出 [1, 5, 10, 3]

        // 删除元素
        list.remove(2);  // 删除索引 2 位置的元素
        System.out.println(list);  // 输出 [1, 5, 3]
    }
}

10. 总结

特性 Array(数组) ArrayList
大小 固定大小,创建时指定 动态大小,自动扩容
存储类型 支持基本数据类型和对象 只能存储对象(需包装类)
访问效率 O(1) O(1)
插入删除效率 插入删除效率低,特别是在中间位置 插入删除效率较低,特别是在中间位置
内存管理 静态分配内存,大小固定 动态分配内存,扩容时复制元素
灵活性 不够灵活 很灵活,适合动态数据操作
  • 数组(Array):适用于大小固定的情况,访问速度快,但不适合频繁插入和删除操作。
  • ArrayList:适用于需要动态扩展和灵活操作的场景,但在插入和删除操作中可能会有性能损失,尤其是在大规模数据操作时。
Java碎碎念 文章被收录于专栏

来一杯咖啡,聊聊Java的碎碎念呀

全部评论
ArrayList通过自动装箱(autoboxing)机制,ArrayList 可以存储 Integer、Double 等包装类对象,间接地存储基本数据类型。 ArrayList的默认大小是10
点赞 回复 分享
发布于 02-06 10:47 广西

相关推荐

&nbsp;&nbsp;&nbsp;&nbsp;黑马点评项目的性能优化&nbsp;主要做了哪些&nbsp;&nbsp;&nbsp;&nbsp;redis分布式锁是乐观锁麻&nbsp;实现原理是什么&nbsp;&nbsp;&nbsp;&nbsp;redis是单机版的还是分布式的&nbsp;&nbsp;&nbsp;&nbsp;redis采取分布式&nbsp;商品保存在不同的redis下具体是如何处理的&nbsp;如何实现这种分布式&nbsp;包括他的可拓展&nbsp;比如流量很大,对redis扩容,如何保证这个服务是不影响的&nbsp;商品数据应该如何存储呢&nbsp;&nbsp;&nbsp;&nbsp;对秒杀来说如何提高他的并发&nbsp;单个redis实例节点存储会有上限&nbsp;&nbsp;&nbsp;&nbsp;concurrenthashmap实现原理&nbsp;&nbsp;&nbsp;&nbsp;其中的数组是什么&nbsp;在并发条件下&nbsp;什么时候存在冲突需要锁&nbsp;什么时候不需要锁&nbsp;&nbsp;&nbsp;&nbsp;get操作是否需要加锁&nbsp;&nbsp;&nbsp;&nbsp;在get操作的时候&nbsp;同步在写&nbsp;怎么处理呢&nbsp;&nbsp;&nbsp;&nbsp;concurrenthashmap是基于什么考虑的&nbsp;是完全处于提高并发量吗&nbsp;&nbsp;&nbsp;&nbsp;jvm垃圾回收算法&nbsp;&nbsp;&nbsp;&nbsp;分代垃圾回收&nbsp;&nbsp;&nbsp;&nbsp;什么情况会导致OOM&nbsp;&nbsp;&nbsp;&nbsp;双亲委派模型&nbsp;优点&nbsp;&nbsp;&nbsp;&nbsp;有什么例外是不需要采用双亲委派模型&nbsp;举例具体的场景&nbsp;&nbsp;&nbsp;&nbsp;java&nbsp;list数据结构&nbsp;有哪些是和list相关的&nbsp;&nbsp;&nbsp;&nbsp;arraylist如何实现扩容&nbsp;&nbsp;&nbsp;&nbsp;扩容&nbsp;如果内存不够大&nbsp;怎么办&nbsp;&nbsp;&nbsp;&nbsp;设计模式&nbsp;用过哪些&nbsp;&nbsp;&nbsp;&nbsp;解释一下三种类型的设计模式&nbsp;创建型&nbsp;行为性&nbsp;结构性&nbsp;分别是什么&nbsp;举几个例子&nbsp;&nbsp;&nbsp;&nbsp;策略模式是什么类型&nbsp;&nbsp;&nbsp;&nbsp;springcloud&nbsp;的&nbsp;rpc&nbsp;是什么&nbsp;注册和发现的实现原理是什么&nbsp;&nbsp;&nbsp;&nbsp;负载均衡算法了解多少&nbsp;&nbsp;&nbsp;&nbsp;一致性哈希算法&nbsp;&nbsp;&nbsp;&nbsp;一致性哈希算法&nbsp;如何实现动态的添加和删除节点的问题&nbsp;&nbsp;&nbsp;&nbsp;具体是用什么实现的&nbsp;后面是用什么数据结构实现的-哈希环&nbsp;&nbsp;&nbsp;&nbsp;数据库&nbsp;&nbsp;&nbsp;&nbsp;隔离级别有几种&nbsp;&nbsp;&nbsp;&nbsp;每种隔离级别是如何实现的&nbsp;实现原理是什么&nbsp;&nbsp;&nbsp;&nbsp;一张表&nbsp;两个事务分别在改&nbsp;那四种隔离级别是如何实现的&nbsp;底层原理&nbsp;是什么&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;会有一个版本在事务提交的时候&nbsp;是把表复制一份还是如何操作的&nbsp;&nbsp;&nbsp;&nbsp;事务回滚&nbsp;有哪些实现方式&nbsp;比如部分回滚如何做&nbsp;底层原理是什么&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;事务未提交&nbsp;如何影响主表的数据呢&nbsp;&nbsp;&nbsp;&nbsp;数据库索引的类型&nbsp;分为哪些&nbsp;&nbsp;&nbsp;&nbsp;复合索引的数据结构是什么&nbsp;&nbsp;是如何对多列的值进行存储的被拷打麻了&nbsp;50min狠狠被拷打
点赞 评论 收藏
分享
评论
点赞
1
分享

创作者周榜

更多
牛客网
牛客网在线编程
牛客网题解
牛客企业服务