ArrayList可以说是大家平时很常用的集合了,那么在这里我们来根据源码试着仿写一下ArrayList以及进行分析
/*
* Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved.
* ORACLE PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*/
package java.util;
/**
* Resizable-array implementation of the <tt>List</tt> interface. Implements
* all optional list operations, and permits all elements, including
* <tt>null</tt>. In addition to implementing the <tt>List</tt> interface,
* this class provides methods to manipulate the size of the array that is
* used internally to store the list. (This class is roughly equivalent to
* <tt>Vector</tt>, except that it is unsynchronized.)
*
* <p>The <tt>size</tt>, <tt>isEmpty</tt>, <tt>get</tt>, <tt>set</tt>,
* <tt>iterator</tt>, and <tt>listIterator</tt> operations run in constant
* time. The <tt>add</tt> operation runs in <i>amortized constant time</i>,
* that is, adding n elements requires O(n) time. All of the other operations
* run in linear time (roughly speaking). The constant factor is low compared
* to that for the <tt>LinkedList</tt> implementation.
*
* <p>Each <tt>ArrayList</tt> instance has a <i>capacity</i>. The capacity is
* the size of the array used to store the elements in the list. It is always
* at least as large as the list size. As elements are added to an ArrayList,
* its capacity grows automatically. The details of the growth policy are not
* specified beyond the fact that adding an element has constant amortized
* time cost.
*
* <p>An application can increase the capacity of an <tt>ArrayList</tt> instance
* before adding a large number of elements using the <tt>ensureCapacity</tt>
* operation. This may reduce the amount of incremental reallocation.
*
* <p><strong>Note that this implementation is not synchronized.</strong>
* If multiple threads access an <tt>ArrayList</tt> instance concurrently,
* and at least one of the threads modifies the list structurally, it
* <i>must</i> be synchronized externally. (A structural modification is
* any operation that adds or deletes one or more elements, or explicitly
* resizes the backing array; merely setting the value of an element is not
* a structural modification.) This is typically accomplished by
* synchronizing on some object that naturally encapsulates the list.
*
* If no such object exists, the list should be "wrapped" using the
* {@link Collections#synchronizedList Collections.synchronizedList}
* method. This is best done at creation time, to prevent accidental
* unsynchronized access to the list:<pre>
* List list = Collections.synchronizedList(new ArrayList(...));</pre>
*
* <p><a name="fail-fast"/>
* The iterators returned by this class's {@link #iterator() iterator} and
* {@link #listIterator(int) listIterator} methods are <em>fail-fast</em>:
* if the list is structurally modified at any time after the iterator is
* created, in any way except through the iterator's own
* {@link ListIterator#remove() remove} or
* {@link ListIterator#add(Object) add} methods, the iterator will throw a
* {@link ConcurrentModificationException}. Thus, in the face of
* concurrent modification, the iterator fails quickly and cleanly, rather
* than risking arbitrary, non-deterministic behavior at an undetermined
* time in the future.
*
* <p>Note that the fail-fast behavior of an iterator cannot be guaranteed
* as it is, generally speaking, impossible to make any hard guarantees in the
* presence of unsynchronized concurrent modification. Fail-fast iterators
* throw {@code ConcurrentModificationException} on a best-effort basis.
* Therefore, it would be wrong to write a program that depended on this
* exception for its correctness: <i>the fail-fast behavior of iterators
* should be used only to detect bugs.</i>
*
* <p>This class is a member of the
* <a href="{@docRoot}/../technotes/guides/collections/index.html">
* Java Collections Framework</a>.
*
* @author Josh Bloch
* @author Neal Gafter
* @see Collection
* @see List
* @see LinkedList
* @see Vector
* @since 1.2
*/
public class ArrayList<E> extends AbstractList<E>
implements List<E>, RandomAccess, Cloneable, java.io.Serializable
{
private static final long serialVersionUID = 8683452581122892189L;
/**
* Default initial capacity.
*/
private static final int DEFAULT_CAPACITY = 10;
/**
* Shared empty array instance used for empty instances.
*/
private static final Object[] EMPTY_ELEMENTDATA = {};
/**
* The array buffer into which the elements of the ArrayList are stored.
* The capacity of the ArrayList is the length of this array buffer. Any
* empty ArrayList with elementData == EMPTY_ELEMENTDATA will be expanded to
* DEFAULT_CAPACITY when the first element is added.
*/
private transient Object[] elementData;
- 首先ArrayList来自 package java.util;
- 由源码得知ArrayList实现了List<E>, RandomAccess, Cloneable, java.io.Serializable
- 实现了RandomAccess接口标识着其支持随机快速访问,实际上,我们查看RandomAccess源码可以看到,其实里面什么都没有定义.因为ArrayList底层是数组,那么随机快速访问是理所当然的
- 实现了Cloneable接口,标识着可以它可以被复制。
因为ArrayList底层使用数组实现,所以优缺点与数组类似。
优点:
- 根据下标遍历元素效率较高。
- 根据下标访问元素效率较高。
- 在数组的基础上封装了对元素操作的方法。
- 可以自动扩容(而他的扩容实现是在把之前的数组复制重新付给一个新得数组在赋值给Value,
在jdk1.8新增加的容量长度为原来容量的1.5倍
)
缺点:
- 插入和删除的效率比较低。
- 根据内容查找元素的效率较低。
- ArrayList不是线程安全的
下面我们模仿源码写几个方法示例
package com.aozhi.test;
import java.util.ArrayList;
/**
* @author songhaibo
*
*/
public class MyArrayList {
/** The value is used for Object storage. */
private Object[] value;
/**
* The size is the number of int used.
*/
private int size;
public MyArrayList() {
//value = new Object[10];
this(10);//this直接调用另一个构造器
}
public MyArrayList(int size) {
if (size < 0) {
try {
throw new Exception();//手动抛出一个异常
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
value = new Object[size];
}
public void add(Object obj) {
value[size] = obj;
size++;
if (size >= value.length) {
//装不下了该扩容了
int newCapacity = value.length * 2;
Object[] newList = new Object[newCapacity];
for (int i = 0; i < value.length; i++) {
newList[i] = value[i];
}
value = newList;
}
}
public Object get(int index) {
rangeCheck(index);
return value[index];
}
public int indexOf(Object obj) {
if (obj == null) {
return -1;
} else {
for (int i = 0; i < value.length; i++) {
if (obj == value[i]) {
return i;
}
}
}
return -1;
}
public int lastIndexOf(Object obj) {
if (obj == null) {
return -1;
} else {
for (int i = value.length - 1; i >= 0; i--) {
if (obj == value[i]) {
return i;//return 的两个作用 第一返回值 第二停止嘛
}
}
}
return -1;
}
public Object set(int index, Object object) {
rangeCheck(index);
Object old = value[index];
value[index] = object;
return old;
}
public void rangeCheck(int index) {
if (index < 0 || index > size - 1) {//[0,size-1]之间
try {
throw new Exception();//手动抛出一个异常
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
public int size() {
return size;
}
public boolean isEmpty() {
return size == 0;
}
public static void main(String[] args) {
MyArrayList list = new MyArrayList(2);
list.add("aaa");
list.add(new Human("宋海波"));
list.add("bbbb");
list.add("bbbb");
list.add("bbbb");
list.add("bbbb");
ArrayList list2;
Human ha = (Human) list.get(1);
System.out.println(ha.getName());
//System.out.println(list.get(2));
System.out.println(list.size());
}
}