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 广西

相关推荐

评论
点赞
1
分享

创作者周榜

更多
牛客网
牛客企业服务