Java集合ArrayList源代码详细解析

一、ArrayList简介

  ArrayList是可以动态增长和缩减的索引序列,它是基于数组实现的List类。

  该类封装了一个动态再分配的Object[]数组,每一个类对象都有一个capacity属性,表示它们所封装的Object[]数组的长度,当向ArrayList中添加元素时,该属性值会自动增加。如果想ArrayList中添加大量元素,可使用ensureCapacity方法一次性增加capacity,可以减少增加重分配的次数提高性能。

  ArrayList的用法和Vector向类似,但是Vector是一个较老的集合,具有很多缺点,不建议使用。另外,ArrayList和Vector的区别是:ArrayList是线程不安全的,当多条线程访问同一个ArrayList集合时,程序需要手动保证该集合的同步性,而Vector则是线程安全的。

  ArrayList与Collection关系如下图:

  

回到顶部

二、ArrayList源码分析

  下面就ArrayList的源代码进行简单的分析:

复制代码

1public class ArrayList<E> extends AbstractList<E> implements List<E>, RandomAccess, Cloneable, java.io.Serializable 2{ 3 private static final long serialVersionUID = 8683452581122892189L; 4 //默认的初始容量为10 5 private static final int DEFAULT_CAPACITY = 10; 6 private static final Object[] EMPTY_ELEMENTDATA = {}; 7 private static final Object[] DEFAULTCAPACITY_EMPTY_ELEMENTDATA = {}; 8 transient Object[] elementData; 9 // ArrayList中实际数据的数量 10 private int size; 11 public ArrayList(int initialCapacity) //带初始容量大小的构造函数 12 { 13 if (initialCapacity > 0) //初始容量大于0,实例化数组 14 { 15 this.elementData = new Object[initialCapacity]; 16 } 17 else if (initialCapacity == 0) //初始化等于0,将空数组赋给elementData 18 { 19 this.elementData = EMPTY_ELEMENTDATA; 20 } 21 else //初始容量小于,抛异常 22 { 23 throw new IllegalArgumentException("Illegal Capacity: "+ initialCapacity); 24 } 25 } 26 public ArrayList() //无参构造函数,默认容量为10 27 { 28 this.elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA; 29 } 30 public ArrayList(Collection<? extends E> c) //创建一个包含collection的ArrayList 31 { 32 elementData = c.toArray(); //返回包含c所有元素的数组 33 if ((size = elementData.length) != 0) 34 { 35 if (elementData.getClass() != Object[].class) 36 elementData = Arrays.copyOf(elementData, size, Object[].class);//复制指定数组,使elementData具有指定长度 37 } 38 else 39 { 40 //c中没有元素 41 this.elementData = EMPTY_ELEMENTDATA; 42 } 43 } 44 //将当前容量值设为当前实际元素大小 45 public void trimToSize() 46 { 47 modCount++; 48 if (size < elementData.length) 49 { 50 elementData = (size == 0)? EMPTY_ELEMENTDATA:Arrays.copyOf(elementData, size); 51 } 52 } 53 54 //将集合的capacit增加minCapacity 55 public void ensureCapacity(int minCapacity) 56 { 57 int minExpand = (elementData != DEFAULTCAPACITY_EMPTY_ELEMENTDATA)?0:DEFAULT_CAPACITY; 58 if (minCapacity > minExpand) 59 { 60 ensureExplicitCapacity(minCapacity); 61 } 62 } 63 private void ensureCapacityInternal(int minCapacity) 64 { 65 if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA) 66 { 67 minCapacity = Math.max(DEFAULT_CAPACITY, minCapacity); 68 } 69 ensureExplicitCapacity(minCapacity); 70 } 71 private void ensureExplicitCapacity(int minCapacity) 72 { 73 modCount++; 74 if (minCapacity - elementData.length > 0) 75 grow(minCapacity); 76 } 77 private static final int MAX_ARRAY_SIZE = Integer.MAX_VALUE - 8; 78 private void grow(int minCapacity) 79 { 80 int oldCapacity = elementData.length;     //注意此处扩充capacity的方式是将其向右一位再加上原来的数,实际上是扩充了1.5倍 81 int newCapacity = oldCapacity + (oldCapacity >> 1); 82 if (newCapacity - minCapacity < 0) 83 newCapacity = minCapacity; 84 if (newCapacity - MAX_ARRAY_SIZE > 0) 85 newCapacity = hugeCapacity(minCapacity); 86 elementData = Arrays.copyOf(elementData, newCapacity); 87 } 88 private static int hugeCapacity(int minCapacity) 89 { 90 if (minCapacity < 0) // overflow 91 throw new OutOfMemoryError(); 92 return (minCapacity > MAX_ARRAY_SIZE) ? 93 Integer.MAX_VALUE : 94 MAX_ARRAY_SIZE; 95 } 96 //返回ArrayList的大小 97 public int size() 98 { 99 return size; 100 } 101 //判断ArrayList是否为空 102 public boolean isEmpty() { 103 return size == 0; 104 } 105 //判断ArrayList中是否包含Object(o) 106 public boolean contains(Object o) { 107 return indexOf(o) >= 0; 108 } 109 //正向查找,返回ArrayList中元素Object(o)的索引位置 110 public int indexOf(Object o) 111 { 112 if (o == null) { 113 for (int i = 0; i < size; i++) 114 if (elementData[i]==null) 115 return i; 116 } 117 else 118 { 119 for (int i = 0; i < size; i++) 120 if (o.equals(elementData[i])) 121 return i; 122 } 123 return -1; 124 } 125 //逆向查找,返回返回ArrayList中元素Object(o)的索引位置 126 public int lastIndexOf(Object o) { 127 if (o == null) { 128 for (int i = size-1; i >= 0; i--) 129 if (elementData[i]==null) 130 return i; 131 } else { 132 for (int i = size-1; i >= 0; i--) 133 if (o.equals(elementData[i])) 134 return i; 135 } 136 return -1; 137 } 138 //返回此 ArrayList实例的浅拷贝。 139 public Object clone() 140 { 141 try 142 { 143 ArrayList<?> v = (ArrayList<?>) super.clone(); 144 v.elementData = Arrays.copyOf(elementData, size); 145 v.modCount = 0; 146 return v; 147 } 148 catch (CloneNotSupportedException e) { 149 // this shouldn't happen, since we are Cloneable 150 throw new InternalError(e); 151 } 152 } 153 //返回一个包含ArrayList中所有元素的数组 154 public Object[] toArray() { 155 return Arrays.copyOf(elementData, size); 156 } 157 @SuppressWarnings("unchecked") 158 public <T> T[] toArray(T[] a) { 159 if (a.length < size) 160 return (T[]) Arrays.copyOf(elementData, size, a.getClass()); 161 System.arraycopy(elementData, 0, a, 0, size); 162 if (a.length > size) 163 a[size] = null; 164 return a; 165 } 166 @SuppressWarnings("unchecked") 167 E elementData(int index) { 168 return (E) elementData[index]; 169 } 170 171 //返回至指定索引的值 172 public E get(int index) 173 { 174 rangeCheck(index); //检查给定的索引值是否越界 175 return elementData(index); 176 } 177 178 //将指定索引上的值替换为新值,并返回旧值 179 public E set(int index, E element) 180 { 181 rangeCheck(index); 182 E oldValue = elementData(index); 183 elementData[index] = element; 184 return oldValue; 185 } 186 187 //将指定的元素添加到此列表的尾部 188 public boolean add(E e) 189 { 190 ensureCapacityInternal(size + 1); 191 elementData[size++] = e; 192 return true; 193 } 194 195 // 将element添加到ArrayList的指定位置 196 public void add(int index, E element) { 197 rangeCheckForAdd(index); 198 ensureCapacityInternal(size + 1); 199 200 //从指定源数组中复制一个数组,复制从指定的位置开始,到目标数组的指定位置结束。 201 //arraycopy(被复制的数组, 从第几个元素开始复制, 要复制到的数组, 从第几个元素开始粘贴, 一共需要复制的元素个数) 202 //即在数组elementData从index位置开始,复制到index+1位置,共复制size-index个元素 203 System.arraycopy(elementData, index, elementData, index + 1,size - index); 204 elementData[index] = element; 205 size++; 206 } 207 208 //删除ArrayList指定位置的元素 209 public E remove(int index) 210 { 211 rangeCheck(index); 212 modCount++; 213 E oldValue = elementData(index); 214 int numMoved = size - index - 1; 215 if (numMoved > 0) 216 System.arraycopy(elementData, index+1, elementData, index,numMoved); 217 elementData[--size] = null; //将原数组最后一个位置置为null 218 return oldValue; 219 } 220 221 //移除ArrayList中首次出现的指定元素(如果存在)。 222 public boolean remove(Object o) { 223 if (o == null) 224 { 225 for (int index = 0; index < size; index++) 226 if (elementData[index] == null) 227 { 228 fastRemove(index); 229 return true; 230 } 231 } 232 else 233 { 234 for (int index = 0; index < size; index++) 235 if (o.equals(elementData[index])) 236 { 237 fastRemove(index); 238 return true; 239 } 240 } 241 return false; 242 } 243 244 //快速删除指定位置的元素 245 private void fastRemove(int index) 246 { 247 modCount++; 248 int numMoved = size - index - 1; 249 if (numMoved > 0) 250 System.arraycopy(elementData, index+1, elementData, index, numMoved); 251 elementData[--size] = null; 252 } 253 254 //清空ArrayList,将全部的元素设为null 255 public void clear() 256 { 257 modCount++; 258 for (int i = 0; i < size; i++) 259 elementData[i] = null; 260 size = 0; 261 } 262 263 //按照c的迭代器所返回的元素顺序,将c中的所有元素添加到此列表的尾部 264 public boolean addAll(Collection<? extends E> c) { 265 Object[] a = c.toArray(); 266 int numNew = a.length; 267 ensureCapacityInternal(size + numNew); // Increments modCount 268 System.arraycopy(a, 0, elementData, size, numNew); 269 size += numNew; 270 return numNew != 0; 271 } 272 273 //从指定位置index开始,将指定c中的所有元素插入到此列表中 274 public boolean addAll(int index, Collection<? extends E> c) { 275 rangeCheckForAdd(index); 276 Object[] a = c.toArray(); 277 int numNew = a.length; 278 ensureCapacityInternal(size + numNew); // Increments modCount 279 int numMoved = size - index; 280 if (numMoved > 0) 281 //先将ArrayList中从index开始的numMoved个元素移动到起始位置为index+numNew的后面去 282 System.arraycopy(elementData, index, elementData, index + numNew, numMoved); 283 //再将c中的numNew个元素复制到起始位置为index的存储空间中去 284 System.arraycopy(a, 0, elementData, index, numNew); 285 size += numNew; 286 return numNew != 0; 287 } 288 289 //删除fromIndex到toIndex之间的全部元素 290 protected void removeRange(int fromIndex, int toIndex) 291 { 292 modCount++; 293 //numMoved为删除索引后面的元素个数 294 int numMoved = size - toIndex; 295 //将删除索引后面的元素复制到以fromIndex为起始位置的存储空间中去 296 System.arraycopy(elementData, toIndex, elementData, fromIndex,numMoved); 297 int newSize = size - (toIndex-fromIndex); 298 //将ArrayList后面(toIndex-fromIndex)个元素置为null 299 for (int i = newSize; i < size; i++) 300 { 301 elementData[i] = null; 302 } 303 size = newSize; 304 } 305 306 //检查索引是否越界 307 private void rangeCheck(int index) 308 { 309 if (index >= size) 310 throw new IndexOutOfBoundsException(outOfBoundsMsg(index)); 311 } 312 private void rangeCheckForAdd(int index) 313 { 314 if (index > size || index < 0) 315 throw new IndexOutOfBoundsException(outOfBoundsMsg(index)); 316 } 317 318 private String outOfBoundsMsg(int index) { 319 return "Index: "+index+", Size: "+size; 320 } 321 322 //删除ArrayList中包含在c中的元素 323 public boolean removeAll(Collection<?> c) 324 { 325 Objects.requireNonNull(c); 326 return batchRemove(c, false); 327 } 328 329 //删除ArrayList中除包含在c中的元素,和removeAll相反 330 public boolean retainAll(Collection<?> c) 331 { 332 Objects.requireNonNull(c); //检查指定对象是否为空 333 return batchRemove(c, true); 334 } 335 336 private boolean batchRemove(Collection<?> c, boolean complement) { 337 final Object[] elementData = this.elementData; 338 int r = 0, w = 0; 339 boolean modified = false; 340 try 341 { 342 for (; r < size; r++) 343 if (c.contains(elementData[r]) == complement) //判断c中是否有elementData[r]元素 344 345 elementData[w++] = elementData[r]; 346 } 347 finally 348 { 349 if (r != size) 350 { 351 System.arraycopy(elementData, r, elementData, w, size - r); 352 w += size - r; 353 } 354 if (w != size) 355 { 356 // clear to let GC do its work 357 for (int i = w; i < size; i++) 358 elementData[i] = null; 359 modCount += size - w; 360 size = w; 361 modified = true; 362 } 363 } 364 return modified; 365 } 366 367 //将ArrayList的“容量,所有的元素值”都写入到输出流中 368 private void writeObject(java.io.ObjectOutputStream s) throws java.io.IOException 369 { 370 int expectedModCount = modCount; 371 s.defaultWriteObject(); 372 //写入数组大小 373 s.writeInt(size); 374 //写入所有数组的元素 375 for (int i=0; i<size; i++) { 376 s.writeObject(elementData[i]); 377 } 378 if (modCount != expectedModCount) { 379 throw new ConcurrentModificationException(); 380 } 381 } 382 383 //先将ArrayList的“大小”读出,然后将“所有的元素值”读出 384 private void readObject(java.io.ObjectInputStream s) 385 throws java.io.IOException, ClassNotFoundException { 386 elementData = EMPTY_ELEMENTDATA; 387 s.defaultReadObject(); 388 s.readInt(); // ignored 389 if (size > 0) { 390 // be like clone(), allocate array based upon size not capacity 391 ensureCapacityInternal(size); 392 Object[] a = elementData; 393 // Read in all elements in the proper order. 394 for (int i=0; i<size; i++) { 395 a[i] = s.readObject(); 396 } 397 } 398 }

复制代码

回到顶部

三、ArrayList遍历方式

  ArrayList支持3种遍历方式

  1、通过迭代器遍历:

1Iterator iter = list.iterator(); 2 while (iter.hasNext()) 3 { 4 System.out.println(iter.next()); 5 }

  2、随机访问,通过索引值去遍历,由于ArrayList实现了RandomAccess接口

1int size = list.size(); 2 for (int i=0; i<size; i++) 3 { 4 System.out.println(list.get(i)); 5 }

  3、for循环遍历:

1for(String str:list) 2 { 3 System.out.println(str); 4   }

  完整的代码示例如下:

复制代码

1public class DemoMain 2{ 3 public static void main(String[] args) 4 { 5 List<String> list=new ArrayList<String>(); 6 list.add("nihao"); 7 list.add("xujian"); 8 list.add("wang"); 9 System.out.println("--------通过迭代器遍历---------"); 10 Iterator iter = list.iterator(); 11 while (iter.hasNext()) 12 { 13 System.out.println(iter.next()); 14 } 15 16 System.out.println("--------通过随机访问---------"); 17 int size = list.size(); 18 for (int i=0; i<size; i++) 19 { 20 System.out.println(list.get(i)); 21 } 22 23 System.out.println("--------通过for循环访问---------"); 24 for(String str:list) 25 { 26 System.out.println(str); 27 } 28 } 29}

复制代码

  运行结果如图示:

  

点赞
收藏

评论区

加载中...

相关推荐

手写Java HashMap源码

HashMap的使用教程HashMap的使用教程HashMap的使用教程HashMap的使用教程HashMap的使用教程22

java集合框架

ArrayList简介ArrayList是list接口的可变数组的实现。与一般数组不同的是,它的容量可以动态增长。ArrayList继承了AbstractList抽象类,实现了List,RandomAccess,Cloneable,java.io.Serializable接口,根据实现的接口看,它支持随机访问,支持克隆,支持序列化

java ArrayList集合

ArrayList集合是程序中最常见的一种集合,它属于引用数据类型(类)。在ArrayList内部封装了一个长度可变的数组,当存入的元素超过数组长度时,ArrayList会在内存中分配一个更大的数组来存储这些元素,因此可以将ArrayList集合看作一个长度可变的数组。集合的创建格式导包:importjava.util.ArrayList;

「JDK——ArrayList源码」超强解析,图文详解

ArrayList源码解析简介ArrayList是Java集合框架中非常常用的一种数据结构。继承自AbstractList,实现了List接口。底层基于数组来实现动态容量大小的控制,允许null值的存在。同时还实现了RandomAccess、Cloneable、Serializable接口,支持快速访问、复制、序列化操作。了解数组数组简单来说就是将所有的

ArrayList底层

一、ArrayList集合底层数据结构1.ArrayList集合介绍List集合的可调整大小数组实现。2.数组结构介绍增删快:每次增加删除元素,都需要更改数组长度、拷贝以及移除元素位置。查询快:由于数组在内存中是一块连续空间,因此可以根据地址索引的方式快速获

说说ArrayList的扩容机制

ArrayList是List接口的实现类,它是支持根据需要而动态增长的数组。java中标准数组是定长的,在数组被创建之后,它们不能被加长或缩短。这就意味着在创建数组时需要知道数组的所需长度,但有时我们需要动态程序中获取数组长度。ArrayList就是为此而生的,但是它不是线程安全的,外ArrayList按照插入的顺序来存放数据①ArrayList扩容发生