ArrayList详解
来源:互联网 发布:手机淘宝收藏软件 编辑:程序博客网 时间:2024/05/16 04:43
1.ArrayList简介:
ArrayList继承关系:
public class ArrayList<E> extends AbstractList<E> implements List<E>, RandomAccess, Cloneable, java.io.Serializable
ArrayList是基于数组实现的,是一个动态数组,其容量能自动增长,类似于C语言中的动态申请内存,动态增长内存。
ArrayList不是线程安全的,只能用在单线程环境下,多线程环境下可以考虑用 Collections.synchronizedList(List l)函数返回一个线程安全的ArrayList类,也可以使用concurrent并发包下的CopyOnWriteArrayList类。
ArrayList实现了Serializable接口,因此它支持序列化,能够通过序列化传输,实现了RandomAccess接口,支持快速随机访问,实际上就是通过下标序号进行快速访问,实现了Cloneable接口,能被克隆。
2、ArrayList 成员变量:
序列版本号:
private static final long serialVersionUID = 8683452581122892189L;
内部结构是一个Object类型的数组:
private transient Object[] elementData;
有关键字transient修饰这个Object数组,那么ArrayList中的数据还可以通过持久化保存下来吗?
答:transient默认是不被序列化的。但是,ArrayList实现了Serializable的writeObject(),readObject()方法,实现了自己定义的持久化方式。
/** * Reconstitute the <tt>ArrayList</tt> instance from a stream (that is, * deserialize it). */ private void readObject(java.io.ObjectInputStream s) throws java.io.IOException, ClassNotFoundException { // Read in size, and any hidden stuff s.defaultReadObject(); // Read in array length and allocate array int arrayLength = s.readInt(); Object[] a = elementData = new Object[arrayLength]; // Read in all elements in the proper order. for (int i=0; i<size; i++) a[i] = s.readObject(); }
ArrayList中实际数据的数量 :
private int size;
3、ArrayList构造函数:
1、ArrayList无参构造函数。默认容量是10 。
public ArrayList() { this(10); }
2、ArrayList带容量大小的构造函数
public ArrayList(int initialCapacity) { super(); if (initialCapacity < 0) throw new IllegalArgumentException("Illegal Capacity: " + initialCapacity); this.elementData = new Object[initialCapacity]; }
3、 创建一个包含collection的ArrayList
public ArrayList(Collection<? extends E> c) { elementData = c.toArray(); size = elementData.length; // c.toArray might (incorrectly) not return Object[] (see 6260652) if (elementData.getClass() != Object[].class) elementData = Arrays.copyOf(elementData, size, Object[].class); }
4、ArrayList常用方法
1、add()方法:
// 确定ArrarList的容量。 // 若ArrayList的容量不足以容纳当前的全部元素,设置 新的容量=“(原始容量x3)/2 + 1” public void ensureCapacity(int minCapacity) { // 将“修改统计数”+1,该变量主要是用来实现fail-fast机制的 modCount++; int oldCapacity = elementData.length; // 若当前容量不足以容纳当前的元素个数,设置 新的容量=“(原始容量x3)/2 + 1” if (minCapacity > oldCapacity) { Object oldData[] = elementData; int newCapacity = (oldCapacity * 3)/2 + 1; //如果还不够,则直接将minCapacity设置为当前容量 if (newCapacity < minCapacity) newCapacity = minCapacity; elementData = Arrays.copyOf(elementData, newCapacity); } } // 添加元素e public boolean add(E e) { // 确定ArrayList的容量大小 ensureCapacity(size + 1); // Increments modCount!! // 添加e到ArrayList中 elementData[size++] = e; return true; } // 将e添加到ArrayList的指定位置 public void add(int index, E element) { if (index > size || index < 0) throw new IndexOutOfBoundsException( "Index: "+index+", Size: "+size); ensureCapacity(size+1); // Increments modCount!! System.arraycopy(elementData, index, elementData, index + 1, size - index); elementData[index] = element; size++; } // 将集合c追加到ArrayList中 public boolean addAll(Collection<? extends E> c) { Object[] a = c.toArray(); int numNew = a.length; ensureCapacity(size + numNew); // Increments modCount System.arraycopy(a, 0, elementData, size, numNew); size += numNew; return numNew != 0; }
当ArrayList容量不足以容纳全部元素时,ArrayList会重新设置容量:新的容量=“(原始容量x3)/2 + 1”。
2、remove()方法:
/** * Removes the element at the specified position in this list. * Shifts any subsequent elements to the left (subtracts one from their * indices). * * @param index the index of the element to be removed * @return the element that was removed from the list * @throws IndexOutOfBoundsException {@inheritDoc} */ public E remove(int index) { RangeCheck(index); modCount++; E oldValue = (E) elementData[index]; int numMoved = size - index - 1; if (numMoved > 0) System.arraycopy(elementData, index+1, elementData, index, numMoved); elementData[--size] = null; // Let gc do its work return oldValue; } /** * Removes the first occurrence of the specified element from this list, * if it is present. If the list does not contain the element, it is * unchanged. More formally, removes the element with the lowest index * <tt>i</tt> such that * <tt>(o==null ? get(i)==null : o.equals(get(i)))</tt> * (if such an element exists). Returns <tt>true</tt> if this list * contained the specified element (or equivalently, if this list * changed as a result of the call). * * @param o element to be removed from this list, if present * @return <tt>true</tt> if this list contained the specified element */ // 删除元素 public boolean remove(Object o) { if (o == null) { for (int index = 0; index < size; index++) if (elementData[index] == null) { fastRemove(index); return true; } } else { // 便利ArrayList,找到“元素o”,则删除,并返回true。 for (int index = 0; index < size; index++) if (o.equals(elementData[index])) { fastRemove(index); return true; } } return false; }
3、查找方法:
//正向查找到指定元素,返回索引public int indexOf(Object o) { if (o == null) { for (int i = 0; i < size; i++) if (elementData[i]==null) return i; } else { for (int i = 0; i < size; i++) if (o.equals(elementData[i])) return i; } return -1; }
//反向查找到指定元素,返回索引public int lastIndexOf(Object o) { if (o == null) { for (int i = size-1; i >= 0; i--) if (elementData[i]==null) return i; } else { for (int i = size-1; i >= 0; i--) if (o.equals(elementData[i])) return i; } return -1; }
//获得索引元素处的值public E get(int index) { RangeCheck(index); return (E) elementData[index]; }
4、修改方法:
public E set(int index, E element) { RangeCheck(index); E oldValue = (E) elementData[index]; elementData[index] = element; return oldValue; }
5、contains(Object o)方法:
public boolean contains(Object o) { return indexOf(o) >= 0; }
6、clone()方法:
public Object clone() { try { ArrayList<E> v = (ArrayList<E>) super.clone(); // 将当前ArrayList的全部元素拷贝到v中 v.elementData = Arrays.copyOf(elementData, size); v.modCount = 0; return v; } catch (CloneNotSupportedException e) { // this shouldn't happen, since we are Cloneable throw new InternalError(); } }
5、ArrayList遍历方式:
1、通过迭代器遍历。即通过Iterator去遍历。
Integer value = null; Iterator iter = list.iterator(); while (iter.hasNext()) { value = (Integer)iter.next(); }
2、 随机访问,通过索引值去遍历。由于ArrayList实现了RandomAccess接口,它支持通过索引值去随机访问元素。
Integer value = null; int size = list.size(); for (int i=0; i<size; i++) { value = (Integer)list.get(i); }
3、for循环遍历
Integer value = null; for (Integer integ:list) { value = integ; }
6、总结:
1、注意其三个不同的构造方法。无参构造方法构造的ArrayList的容量默认为10,带有Collection参数的构造方法,将Collection转化为数组赋给ArrayList的实现数组elementData。
2、注意扩充容量的方法ensureCapacity。ArrayList在每次增加元素(可能是1个,也可能是一组)时,都要调用该方法来确保足够的容量。设置新的容量为旧的容量的1.5倍加1。
3、注意ArrayList的两个转化为静态数组的toArray方法。
第一个,Object[] toArray()方法。该方法有可能会抛出java.lang.ClassCastException异常,如果直接用向下转型的方法,将整个ArrayList集合转变为指定类型的Array数组,便会抛出该异常,而如果转化为Array数组时不向下转型,而是将每个元素向下转型,则不会抛出该异常,显然对数组中的元素一个个进行向下转型,效率不高,且不太方便。
第二个, T[] toArray(T[] a)方法。该方法可以直接将ArrayList转换得到的Array进行整体向下转型(转型其实是在该方法的源码中实现的),且从该方法的源码中可以看出,参数a的大小不足时,内部会调用Arrays.copyOf方法,该方法内部创建一个新的数组返回。
5、ArrayList基于数组实现,可以通过下标索引直接查找到指定位置的元素,因此查找效率高,但每次插入或删除元素,就要大量地移动元素,插入删除元素的效率低。
6、在查找给定元素索引值等的方法中,源码都将该元素的值分为null和不为null两种情况处理,ArrayList中允许元素为null。
参考资料:
Java容器类—ArrayList
- ArrayList详解
- ArrayList详解
- ArrayList详解
- ArrayList详解
- ArrayList详解
- ArrayList详解
- ArrayList详解
- ArrayList详解
- arraylist详解
- ArrayList详解
- ArrayList详解应用
- Vector、ArrayList、List详解
- java ArrayList详解
- C# ArrayList详解
- ArrayList详解(1)
- ArrayList使用详解
- ArrayList源码详解
- ArrayList源码详解
- HDU 1019 Least Common Multiple (最小公倍数_水题)
- 实习一周总结
- Android中shape的使用
- C++推荐经典书籍
- MAVEN自动部署到tomcat
- ArrayList详解
- CLLocationManager的相关属性讲解
- HiWork发布1.5.0新版本——集成第三方应用达到44种
- MyBatis简介与配置MyBatis+Spring+MySql
- 端口被占用
- Anaconda 安装 PSYCOPG2 on windows
- POJ 2367 -- Genealogical tree【拓扑排序 && 水题】
- 桥接模式(Bridge)
- 电驴资源下载