Java笔记集合之ArrayList

1、ArrayList简介

List 接口的大小可变数组的实现。实现了所有可选列表操作,并允许包括null 在内的所有元素。除了实现 List 接口外,此类还提供一些方法来操作内部用来存储列表的数组的大小。(此类大致上等同于Vector 类,除了此类是不同步的。)

sizeisEmptygetsetiterator listIterator 操作都以固定时间运行。add 操作以分摊的固定时间 运行,也就是说,添加 n 个元素需要 O(n) 时间。其他所有操作都以线性时间运行(大体上讲)。与用于LinkedList 实现的常数因子相比,此实现的常数因子较低。

每个 ArrayList 实例都有一个容量。该容量是指用来存储列表元素的数组的大小。它总是至少等于列表的大小。随着向 ArrayList 中不断添加元素,其容量也自动增长。并未指定增长策略的细节,因为这不只是添加元素会带来分摊固定时间开销那样简单。

在添加大量元素前,应用程序可以使用 ensureCapacity 操作来增加 ArrayList 实例的容量。这可以减少递增式再分配的数量。

注意,此实现不是同步的。

ArrayList就是传说中的动态数组,用MSDN中的说法,就是Array的复杂版本,它提供了如下一些好处:

  • 动态的增加和减少元素
  • 实现了ICollection和IList接口
  • 灵活的设置数组的大小

2、方法摘要

构造方法
ArrayList()
          构造一个初始容量为 10 的空列表。
ArrayList(Collection c)
          构造一个包含指定 collection 的元素的列表,这些元素是按照该 collection 的迭代器返回它们的顺序排列的。
ArrayList(int initialCapacity)
          构造一个具有指定初始容量的空列表。

方法摘要
boolean add(E e)
          将指定的元素添加到此列表的尾部。
    void add(int index, E element)
          将指定的元素插入此列表中的指定位置。
boolean     ddAll(Collection c)
          按照指定 collection 的迭代器所返回的元素顺序,将该 collection 中的所有元素添加到此列表的尾部。
boolean  addAll(int index, Collection c)
          从指定的位置开始,将指定 collection 中的所有元素插入到此列表中。
void clear()
          移除此列表中的所有元素。
 Object clone()
          返回此 ArrayList 实例的浅表副本
boolean contains(Object o)
          如果此列表中包含指定的元素,则返回 true
   void ensureCapacity(int minCapacity)
          如有必要,增加此 ArrayList 实例的容量,以确保它至少能够容纳最小容量参数所指定的元素数。
 E get(int index)
          返回此列表中指定位置上的元素
    int indexOf(Object o)
          返回此列表中首次出现的指定元素的索引,或如果此列表不包含元素,则返回 -1。
boolean isEmpty()
          如果此列表中没有元素,则返回 true
 int lastIndexOf(Object o)
          返回此列表中最后一次出现的指定元素的索引,或如果此列表不包含索引,则返回 -1。
 E remove(int index)
          移除此列表中指定位置上的元素。
boolean remove(Object o)
          移除此列表中首次出现的指定元素(如果存在)。
protected  void removeRange(int fromIndex, int toIndex)
          移除列表中索引在 fromIndex(包括)和 toIndex(不包括)之间的所有元素。移除后,后面的所有元素向前移动
 E set(int index, E element)
          用指定的元素替代此列表中指定位置上的元素。
int size()
          返回此列表中的元素数
Object[] toArray()
          按适当顺序(从第一个到最后一个元素)返回包含此列表中所有元素的数组。
T[]

toArray(T[] a)
          按适当顺序(从第一个到最后一个元素)返回包含此列表中所有元素的数组;返回数组的运行时类型是指定数组的运行时类型。
void trimToSize()
          将此 ArrayList 实例的容量调整为列表的当前大小。

3、部分代码

package com.jlz;

import java.util.*;

public class MyArrayList {

	/**
	 * @param args
	 */
	public static void main(String[] args) {
		// TODO Auto-generated method stub
		ArrayList ayl = new ArrayList();

		for (int i = 1; i <= 10; i++) {
			ayl.add(i);
			// 添加元素
		}

		ayl.remove(5);// 移除第六个位置上的元素6

		// 遍历方法一
		for (int i = 0; i < ayl.size(); i++) {
			System.out.println(ayl.get(i));
		}
		// 遍历方法二
		// 正序
		ListIterator lt = ayl.listIterator();
		while (lt.hasNext()) {
			System.out.println("Iterator: " + lt.next());

		}
		// 倒序
		while (lt.hasPrevious()) {
			System.out.println("Previous: " + lt.previous());
		}

		// 与数组的转换
		Object[] values = ayl.toArray();

		for (int i = 0; i < values.length; i++) {
			System.out.println("Values: " + values[i].toString());
		}
	}

}

4、ArrayList最佳使用建议

ArrayList与数组的差别,以及ArrayList的效率问题
   (1)ArrayList是Array的复杂版本
ArrayList内部封装了一个Object类型的数组,从一般的意义来说,它和数组没有本质的差别,甚至于ArrayList的许多方法,如Index、IndexOf、Contains、Sort等都是在内部数组的基础上直接调用Array的对应方法。
  (2)内部的Object类型的影响
         对于一般的引用类型来说,这部分的影响不是很大, 但是对于值类型来说,往ArrayList里面添加和修改元素,都会引起装箱和拆箱的操作,频繁的操作可能会影响一部分效率。
但是恰恰对于大多数人,多数的应用都是使用值类型的数组。
消除这个影响是没有办法的,除非你不用它,否则就要承担一部分的效率损失,不过这部分的损失不会很大。
   (3)数组扩容
这是对ArrayList效率影响比较大的一个因素。
每当执行Add、AddRange、Insert、InsertRange等添加元素的方法,都会检查内部数组的容量是否不够了,如果是,它就会以当前容量的两倍来重新构建一个数组,将旧元素Copy到新数组中,然后丢弃旧数组,在这个临界点的扩容操作,应该来说是比较影响效率的。
     例1:比如,一个可能有200个元素的数据动态添加到一个以默认16个元素大小创建的ArrayList中,将会经过:
16*2*2*2*2 = 256
四次的扩容才会满足最终的要求,那么如果一开始就以:
ArrayList List = new ArrayList( 210 );
的方式创建ArrayList,不仅会减少4次数组创建和Copy的操作,还会减少内存使用。


      例2:预计有30个元素而创建了一个ArrayList:
ArrayList List = new ArrayList(30);
在执行过程中,加入了31个元素,那么数组会扩充到60个元素的大小,而这时候不会有新的元素再增加进来,而且有没有调用TrimSize方法,那么就有1次扩容的操作,并且浪费了29个元素大小的空间。如果这时候,用:
ArrayList List = new ArrayList(40);
那么一切都解决了。
所以说,正确的预估可能的元素,并且在适当的时候调用TrimSize方法是提高ArrayList使用效率的重要途径。

    (4)频繁的调用IndexOf、Contains等方法(Sort、BinarySearch等方法经过优化,不在此列)引起的效率损失
首先,我们要明确一点,ArrayList是动态数组,它不包括通过Key或者Value快速访问的算法,所以实际上调用IndexOf、Contains等方法是执行的简单的循环来查找元素,所以频繁的调用此类方法并不比你自己写循环并且稍作优化来的快,如果有这方面的要求,建议使用Hashtable或SortedList等键值对的集合。





你可能感兴趣的:(Java)