
ArrayList 总结核心特性、常用接口、代码实现本文聚焦 Java 集合框架中的ArrayList从它的定义与核心特性出发系统梳理所有常用接口的作用与返回值最后给出整体总结。适合作为学习笔记或面试速查。目录一、ArrayList 简介二、ArrayList 的构造方式三、ArrayList 常用接口作用 返回值四、接口使用示例五、模拟实现代码六、总结一、ArrayList 简介在集合框架中ArrayList 是一个普通的类实现了 List 接口它的本质是一个动态类型的顺序表。特性说明泛型实现以泛型方式实现使用时必须先实例化如ArrayListIntegerRandomAccess实现了该接口表明 ArrayList支持随机访问下标访问 O(1)Cloneable实现了该接口表明 ArrayList可以 cloneSerializable实现了该接口表明 ArrayList支持序列化非线程安全与 Vector 不同ArrayList不是线程安全的单线程下使用多线程中可选择Vector或CopyOnWriteArrayList动态扩容底层是一段连续的空间并且可以动态扩容是一个动态类型的顺序表一句话记忆ArrayList 泛型 随机访问 可克隆 可序列化 非线程安全 动态扩容的动态顺序表。底层结构elementData真正的Object[]数组物理地址连续size有效元素个数≠ 数组容量前者是「装了多少」后者是「最多能装多少」。二、ArrayList 的构造方式publicstaticvoidmain(String[]args){// 构造一个空的列表ListIntegerlist1newArrayList();// 构造一个具有 10 个容量的列表ListIntegerlist2newArrayList(10);// 拷贝构造构造好之后与源集合中的元素一致ArrayListIntegerlist3newArrayList(list2);// ⚠️ 避免省略类型否则任意类型都能存放使用时将是一场灾难Listlist4newArrayList();list4.add(111);list4.add(100);}构造方法作用ArrayList()构造一个空的列表首次添加元素时才分配容量10ArrayList(int initialCapacity)构造一个具有指定初始容量的列表可减少扩容次数ArrayList(Collection? extends E c)拷贝构造元素与源集合一致建议始终显式指定泛型否则编译期类型检查失效运行时容易出现类型混乱。三、ArrayList 常用接口作用 返回值以下为 ArrayList / List 最常用的接口逐一给出方法签名、作用、返回值。方法作用返回值boolean add(E e)在列表末尾添加元素添加成功返回truevoid add(int index, E e)在index位置插入元素index 及后续元素统一后移一位无返回值E remove(int index)删除index位置的元素该元素之后的元素统一前移一位返回被删除的元素boolean remove(Object o)删除第一次出现的指定元素删除成功返回true元素不存在返回falseE get(int index)获取index位置的元素index 必须 ∈ [0, size)返回该位置的元素E set(int index, E e)将index位置的元素设为e返回被替换的旧元素boolean contains(Object o)判断列表中是否包含指定元素包含返回true否则返回falseint indexOf(Object o)查找指定元素第一次出现的位置从前往后找找到返回下标未找到返回 -1int lastIndexOf(Object o)查找指定元素最后一次出现的位置从后往前找找到返回下标未找到返回 -1int size()获取列表中有效元素个数返回 size注意不是底层数组容量void clear()清空列表无返回值boolean isEmpty()判断列表是否为空为空返回true否则返回falseListE subList(int fromIndex, int toIndex)截取[fromIndex, toIndex)区间与原列表共用同一个 elementData 数组返回一个 SubList视图非独立副本Object[] toArray()将列表转换为数组返回Object[]数组IteratorE iterator()获取迭代器返回IteratorE对象ListIteratorE listIterator()获取列表迭代器支持双向遍历返回ListIteratorE对象⚠️两个极易踩坑的返回值remove(int index)返回被删除的元素而remove(Object o)返回boolean—— 两个重载方法语义完全不同subList()返回的是原列表的片段视图View与原文 list共享同一个底层数组同一地址修改视图会影响原列表。四、接口使用示例下面通过一段完整的代码演示上述常用接口的实际用法。代码中每一步都配有注释方便对照理解。publicstaticvoidmain(String[]args){// 1. 构造一个空的列表ListStringlistnewArrayList();System.out.println(初始列表list是否为空list.isEmpty());// 2. 在列表末尾依次添加元素list.add(JavaSE);list.add(JavaWeb);list.add(JavaEE);list.add(JVM);list.add(测试课程);System.out.println(添加元素后list);// 3. 获取 list 中有效元素个数注意不是底层数组容量System.out.println(有效元素个数 size list.size());// 4. 获取和设置 index 位置上的元素注意 index 必须介于 [0, size) 间System.out.println(get(1) list.get(1));list.set(1,JavaWEB);// 把下标 1 的元素替换为 JavaWEBSystem.out.println(set 之后 get(1) list.get(1));// 5. 在 list 的 index 位置插入指定元素index 及后续元素统一往后搬移一个位置list.add(1,Java数据结构);System.out.println(在下标 1 插入后list);// 6. 删除指定元素按值删除找到了就删除该元素之后的元素统一往前搬移一个位置list.remove(JVM);System.out.println(删除 JVM 后list);// 7. 删除 index 位置上的元素按下标删除注意 index 不要超过有效元素个数否则抛下标越界异常list.remove(list.size()-1);System.out.println(删除最后一个元素后list);// 8. 检测是否包含指定元素包含返回 true否则返回 falseif(list.contains(测试课程)){list.add(测试课程);System.out.println(包含测试课程已再次添加list);}// 9. 查找指定元素第一次出现的位置indexOf 从前往后找lastIndexOf 从后往前找list.add(JavaSE);System.out.println(indexOf(JavaSE) list.indexOf(JavaSE));System.out.println(lastIndexOf(JavaSE) list.lastIndexOf(JavaSE));// 10. 使 list 中 [0, 4) 之间的元素构成一个新的 SubList 返回但和 ArrayList 共用同一个 elementData 数组ListStringretlist.subList(0,4);System.out.println(subList(0,4) ret);// 11. 清空列表list.clear();System.out.println(清空后 size list.size()是否为空list.isEmpty());}运行结果说明isEmpty()在列表刚创建时返回true添加元素后返回falseset(1, JavaWEB)会返回被替换的旧元素此处为JavaWeb但示例中未打印读者可自行验证add(1, Java数据结构)会把原下标 1 及之后的元素整体后移一位remove(JVM)按值删除删除成功后返回trueremove(list.size() - 1)按下标删除最后一个元素并返回被删除的元素subList(0, 4)返回的是视图修改ret会同步影响原list反之亦然。动手练习试着在subList返回的ret上调用set(0, 修改)再打印原list观察两者是否同步变化从而加深对「视图共享底层数组」的理解。五、模拟实现代码packagemyarraylist;publicclassMyArrayList{//用String来实现privateString[]datanull;privateintsize0;publicMyArrayList(){datanewString[10];}publicMyArrayList(intcapacity){if(capacity10){capacity10;}datanewString[capacity];sizecapacity;}privatevoidresize(){String[]newStringnewString[data.length(data.length1)];for(inti0;isize;i){newString[i]data[i];}datanewString;}publicvoidadd(intindex,Stringvalue){if(index0||indexsize){thrownewIndexOutOfBoundsException();}if(sizedata.length){resize();}for(intisize-1;iindex;i--){data[i1]data[i];}data[index]value;size;}publicvoidadd(Stringelem){if(sizedata.length){resize();}data[size]elem;size1;}publicStringremove(intindex){if(index0||indexsize){thrownewIndexOutOfBoundsException();}Stringelemdata[index];for(intiindex1;isize;i){data[i-1]data[i];}size--;returnelem;}publicBooleanremove(Stringelem){for(inti0;isize;i){if(data[i].equals(elem)){remove(i);//因为这里复用的是上一个删除 上一个删除已经减减所以这里不用渐渐就行returntrue;}}returnfalse;}publicStringget(intindex){if(index0||indexsize){thrownewIndexOutOfBoundsException();}returndata[index];}publicvoidset(intindex,Stringelem){if(index0||indexsize){thrownewIndexOutOfBoundsException();}data[index]elem;}publicvoidclear(){size0;}publicbooleancontains(Stringelem){for(inti0;isize;i){if(data[i].equals(elem)){returntrue;}}returnfalse;}publicintindexOf(Stringelem){for(inti0;isize;i){if(data[i].equals(elem)){returni;}}return-1;}publicintlastIndexOf(Stringelem){for(intisize-1;i0;i--){if(data[i].equals(elem)){returni;}}return-1;}publicMyArrayListsubList(intfromIndex,inttoIndex){if(fromIndex0||toIndex0){thrownewIndexOutOfBoundsException();}MyArrayListlistnewMyArrayList(toIndex-fromIndex);for(intifromIndex;itoIndex;i){list.add(data[i]);}returnlist;}OverridepublicStringtoString(){StringBuilderstrnewStringBuilder();str.append([);for(inti0;isize;i){str.append(data[i]);if(isize-1){break;}str.append(, );}str.append(]);returnstr.toString();}publicstaticvoidmain(String[]args){MyArrayListlistnewMyArrayList();list.add(A);list.add(B);list.add(C);list.add(2,g);list.remove(2);list.remove(A);System.out.println(list);}}六、总结ArrayList 本质Java 集合框架中实现的动态顺序表底层是一段可动态扩容的连续空间核心特性泛型实现、支持随机访问、可 clone、可序列化、非线程安全关键接口add/remove/get/set/contains/indexOf/lastIndexOf/size/clear/subList等需牢记各自作用与返回值易错点remove(int index)返回被删除元素remove(Object o)返回 booleansubList()返回的是共享底层数组的视图并非独立副本size()返回的是有效元素个数不是底层数组容量使用建议已知数据量时预先指定初始容量以减少扩容带来的开销。如果这篇文章对你有帮助欢迎点赞 收藏 ⭐ 关注后续会继续更新 Java 集合框架系列文章