你刚开始学 Java 的时候,是不是也纠结过 “该用数组还是 ArrayList”?比如想存 10 个学生成绩,用数组写 int [] scores = new int [10],后来突然要加第 11 个成绩,结果数组容量不够,只能新建一个更大的数组再把数据复制过去,折腾半天;或者想删除某个成绩,还得手动把后面的元素往前挪,生怕漏了数据 —— 其实这些麻烦事,用 ArrayList 就能轻松解决,小索奇认为这是 Java 新手必搞懂的基础容器,搞清楚它和数组的区别,能少走很多弯路。

先说说数组的 “硬伤”—— 固定容量。你创建数组的时候必须指定大小,比如 new String [5],就只能存 5 个字符串,想多存一个都不行。要是你不确定要存多少数据,比如做一个用户输入的列表,一开始设小了不够用,设大了又浪费内存。而且数组删除元素特别麻烦,比如数组里存着 ["A","B","C","D"],想删掉 “B”,就得把 “C” 挪到 “B” 的位置,“D” 再挪到 “C” 的位置,最后还要把数组长度 “假装” 减 1(其实 Java 数组长度改不了,只能靠逻辑处理),步骤多还容易出错。

而 ArrayList 刚好能补上这些短板。它的容量是 “动态变化” 的,你不用一开始就指定大小,直接 new ArrayList<>() 就行,想存多少元素就 add 多少,比如 add ("A")、add ("B"),存到第 10 个的时候,它会自动扩容(默认初始容量是 10,满了之后会按 1.5 倍扩容,比如 10 满了就扩到 15,15 满了扩到 22,不用你手动处理)。删除元素也简单,直接调用 remove (index) 方法,比如 remove (1) 就能删掉第 2 个元素(ArrayList 索引从 0 开始),后面的元素会自动往前挪,不用你写循环处理,是不是省了很多事?

不过新手用 ArrayList,最容易踩的坑就是 “没搞懂泛型”。比如有人写 ArrayList list = new ArrayList (),没加泛型,结果存的时候又放 String 又放 Integer,取数据的时候还要强制转换,一不小心就报 ClassCastException(类型转换异常)。小索奇得提醒你,一定要用泛型指定元素类型,比如 ArrayList就只能存字符串,ArrayList只能存整数,这样存错类型的时候编译器会直接报错,不用等到运行时才发现问题。而且取数据的时候不用强转,直接 get (index) 就能拿到对应类型的元素,既安全又方便。

再说说两者的性能区别。有人觉得 “ArrayList 自动扩容会变慢”,其实在大多数场景下,这种性能差异可以忽略不计。但如果你的数据量特别大,而且能确定固定大小(比如存 1000 个固定的配置项),用数组会更高效 —— 因为 ArrayList 扩容的时候会新建一个数组,把旧数据复制过去,虽然这个过程很快,但频繁扩容确实会多耗一点资源。这时候你可以在创建 ArrayList 的时候指定初始容量,比如 new ArrayList<>(1000),这样它就不用频繁扩容,性能能跟数组接近,还能保留动态增删的优势,算是个折中方案。

还有个小细节要注意:ArrayList 不能存基本数据类型(比如 int、double),只能存包装类(比如 Integer、Double)。比如你想存整数,不能写 ArrayList,得写 ArrayList。这是因为 Java 里集合框架(包括 ArrayList)只能存对象,而 int 是基本类型,不是对象,Integer 是 int 的包装类,本质是对象,所以才能存。不过从 Java 5 开始有 “自动装箱拆箱”,你可以直接写 list.add (10)(会自动把 int 转成 Integer),取的时候 int num = list.get (0)(会自动把 Integer 转成 int),不用手动转换,这点对新手很友好。

小索奇发现,很多新手会在 “遍历” 的时候混淆两者的用法。数组遍历可以用普通 for 循环(for (int i=0; i<array.length; i++)),也能用增强 for 循环(for (String s : array));ArrayList 遍历除了这两种,还能用水流(stream)遍历,比如 list.stream ().forEach (s -> System.out.println (s)),写法更简洁。不过如果需要遍历的时候获取索引,普通 for 循环会更方便,比如 for (int i=0; i<list.size (); i++),用 get (i) 拿元素的同时还能拿到索引,这点和数组的 for 循环逻辑很像。

你之前用 Java 存数据的时候,是不是也遇到过数组容量不够的麻烦?或者用 ArrayList 的时候踩过泛型、自动装箱的坑?可以在评论区说说你的经历,咱们一起聊聊怎么根据场景选数组和 ArrayList!

我是【即兴小索奇】,点击关注,后台回复 领取,获取更多相关资源

Logo

Agent 垂直技术社区,欢迎活跃、内容共建。

更多推荐