栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

ArrayList常用方法及手撕源码

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

ArrayList常用方法及手撕源码

初识ArrayList 一、简介:

ArrayList是 java 集合框架中比较常用的数据结构了。继承自 AbstractList,实现了 List 接口。底层基于数组实现容量大小动态变化。允许 null 的存在。同时还实现了 RandomAccess、Cloneable、Serializable 接口,所以ArrayList 是支持快速访问、复制、序列化的。

ArrayList底层数据结构是数组,查询快,增删慢,线程不安全,效率高,可以存储重复元素

二、常用方法:

add:添加元素

ArrayList list = new ArrayList<>();

list.add("张三");
list.add("李四");
list.add("王五");
list.add("赵六");

System.out.println(list);

输出结果:

add(int index, String element):在此列表中的指定位置插入指定的元素。

//在此列表中的指定位置插入指定的元素。
list.add(2, "钱七");//在下标为2的位置添加元素

addAll(Collection c):按指定集合的Iterator返回的顺序将指定集合中的所有元素追加到此列表的末尾。

//按指定集合的Iterator返回的顺序将指定集合中的所有元素追加到此列表的末尾。
ArrayList newList = new ArrayList<>();
Collections.addAll(newList, "孙悟空", "猪八戒", "沙和尚");
list.addAll(newList);

输出结果为:

addAll(int index, Collection c):将指定集合中的所有元素插入到此列表中,从指定的位置开始。

ArrayList newList2 = new ArrayList<>();
Collections.addAll(newList2, "如来", "唐僧", "观音");
list.addAll(2, newList2);//在下标为2的位置插入newList2集合

输出结果:

remove:删除该列表中指定位置的元素。

list.remove("钱七");//删除元素为"钱七"的元素
list.remove(6);//删除指定下标的元素

//从此列表中删除指定集合中包含的所有元素。

list.removeAll(newList2);

retainAll:仅保留此列表中包含在指定集合中的元素。

list.retainAll(newList1);

set:用指定的元素替换此列表中指定位置的元素。

list.set(1, "马保国");

size():返回此列表中的元素数。

System.out.println("size = " + list.size());

toArray():以正确的顺序(从第一个到最后一个元素)返回一个包含此列表中所有元素的数组。

Object[] array = list.toArray();
System.out.println(Arrays.toString(array));
三、手撕ArrayList的底层结构

ArrayList的底层结构是一个Object类型的一维数组,继承了AbstractList类,并且实现了List接口, RandomAccess接口和 Cloneable接口。

public class ArrayList extends AbstractList implements List, RandomAccess, Cloneable, java.io.Serializable{

   //默认初始容量。
   private static final int DEFAULT_CAPACITY = 10;
   //没有元素的空数组(长度为0)
   private static final Object[] EMPTY_ELEMENTDATA = {};
   //空内容的数组(长度为0)
   private static final Object[] DEFAULTCAPACITY_EMPTY_ELEMENTDATA = {};
   //容器(ArrayList集合中所有的元素都是存在这个一维数组里的)
   transient Object[] elementData;//new Object[10]   
   //元素个数(指针)
   private int size;
   //数组最大容量
   private static final int MAX_ARRAY_SIZE = Integer.MAX_VALUE - 8;
   //最大容量之所以是Integer的最大值-8,是因为ArrayList的底层就是一个以为数组,一维数组存储在堆内存中,会占用一定的内存空间,比如我们的头部信息,包括了其中的内存地址以及数组长度,数据类型等信息

   //ArrayList的无参构造
   public ArrayList() {
       //构造一个初始容量为10的空列表。
       this.elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA;
   }

   //ArrayList的有参构造
   public ArrayList(int initialCapacity) { //验证初始化容量的合法性
       if (initialCapacity > 0) {
           this.elementData = new Object[initialCapacity];
       } else if (initialCapacity == 0) {
           this.elementData = EMPTY_ELEMENTDATA;
       } else {
           throw new IllegalArgumentException("Illegal Capacity: "+ initialCapacity);
       }
   }

   public boolean add(E e) {
       ensureCapacityInternal(size + 1);  
       elementData[size++] = e;
       return true;
   }

  //使用无参构造创建对象时,第一次添加元素就会进入的判断
   private void ensureCapacityInternal(int minCapacity) {
       if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA) {
           minCapacity = Math.max(DEFAULT_CAPACITY, minCapacity);//minCapacity = 10
       }

       ensureExplicitCapacity(minCapacity);
   }

   private void ensureExplicitCapacity(int minCapacity) {
       modCount++;

       //有溢出意识的代码 -- 判断是否可以扩容(要扩容的长度必须大于原数组的长度)
       if (minCapacity - elementData.length > 0)
           grow(minCapacity);
   }

   private void grow(int minCapacity) {
       // 有溢出意识的代码 -- 计算扩容的容量
       int oldCapacity = elementData.length;
       int newCapacity = oldCapacity + (oldCapacity >> 1);//扩容机制为原数组长度的1.5倍
       if (newCapacity - minCapacity < 0)
           newCapacity = minCapacity;
       if (newCapacity - MAX_ARRAY_SIZE > 0)
           newCapacity = hugeCapacity(minCapacity);
       elementData = Arrays.copyOf(elementData, newCapacity);
   }
   
   private static int hugeCapacity(int minCapacity) {
       if (minCapacity < 0)
           throw new OutOfMemoryError();
       return (minCapacity > MAX_ARRAY_SIZE) ?
           Integer.MAX_VALUE :
           MAX_ARRAY_SIZE;
   }



}  
public static void main(String[] args) {

   ArrayList list = new ArrayList<>();
   list.add("张三");
   list.add("李四");

总结:

  • ArrayList的底层是Object类型的一位数组
  • 在使用无参构造的时候,ArrayList会将数组赋值成没有长度的空数组
  • 在使用有参构造的时候,如果参数大于0,则创建参数长度的数组,如果参数等于0会将数组赋值成没有长度的空数组,如果参数小于0就会报错
  • ArrayList的底层有个变量规定初始化容量为10(DEFAULT_CAPACITY = 10),如果使用无参构造创建ArrayList对象,第一次添加元素的时候,会将底层的Object类型的一维数组初始化为10长度的数组
  • ArrayList的扩容机制是1.5倍(int newCapacity = oldCapacity + (oldCapacity >> 1))
  • ArrayList的最大容量为:Integer.MAX_VALUE-8
转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/878032.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号