List集合代表一个有序集合,集合中每个元素都有其对应的顺序索引。List集合允许使用重复元素,可以通过索引来访问指定位置的集合元素。
1、List接口和ListIterator接口
List作为Collection接口的子接口,可以使用Collection接口里的全部方法。List是有序集合,所以List集合里增加了一些根据索引来操作集合元素的方法:
void add(int index, Object element)//:将元素element插入在List集合的index处。
boolean addAll(int index, Collection c)//:将集合c所包含的所有元素都插入在List集合的index处。
Object get(int index)//:返回集合index索引处的元素。
int lastIndexOf(Object o)//:返回对象o在List集合中最后一次出现的位置索引。
Object remove(int index)//:删除并返回index索引处的元素。
Object set(int index, Object element)//:将index索引处的元素替换成element对象,返回旧元素引用。
List subList(int fromIndex, int toIndex)//:返回从索引fromIndex(包含)到索引toIndex(不包含)处所有集合元素组成的子集合。
List集合可以根据索引来插入、替换和删除集合元素。
public class TestList
{
public static void main(String[] args)
{
List books = new ArrayList();
//向books集合中添加三个元素
books.add(new String("轻量级J2EE企业应用实战"));
books.add(new String("Struts2权威指南"));
books.add(new String("基于J2EE的Ajax宝典"));
System.out.println(books);
//将新字符串对象插入在第二个位置
books.add(1 , new String("ROR敏捷开发最佳实践")); //已添加的对象,和下面语句做对比
for (int i = 0 ; i < books.size() ; i++ )
{
System.out.println(books.get(i));
}
//删除第三个元素
books.remove(2);
System.out.println(books);
//判断指定元素在List集合中位置:输出1,表明位于第二位
System.out.println(books.indexOf(new String("ROR敏捷开发最佳实践")));
//新创建的对象,但是判定和第i位置实例是否相等时候是根据存放对象的
//equals方法来判断是否相等的
//将第二个元素替换成新的字符串对象
books.set(1, new String("Struts2权威指南"));
System.out.println(books);
//将books集合的第二个元素(包括)到第三个元素(不包括)截取称子集合
System.out.println(books.subList(1 , 2));
}
}
输出结果
程序说明:List集合可以使用普通for循环来遍历集合元素。List判断两个对象相等只要通过equals方法比较返回true即可。如在判断“ROR敏捷开发最佳实践”字符串的位置是,新创建了一个新字符串对象,但是程序返回list中和这个object相等的实例在list中的序号。
遍历是list相比set有更大特色的地方。
与set只提供了一个iterator()方法不同,List还额外提供了一个listIteratro()方法,该方法返回一个ListIterator对象,ListIterator接口继承了Iterator接口,提供了专门操作List的方法。
ListIterator接口在Iterator接口基础上增加了如下方法:
这三个方法使得list可以往前面迭代遍历元素。
boolean hasPrevious():返回该迭代器关联集合是否还有上一个元素。
Object previous():返回该迭代器上一个元素。
void add():在指定位置插入一个元素。
String[] books = {"Struts2权威指南", "轻量级J2EE企业应用实战"};
List bookList = new ArrayList();
for (int i = 0; i < books.length ; i++ )
{ bookList.add(books[i]);}
ListIterator lit = bookList.listIterator();
while (lit.hasNext())
{
System.out.println(lit.next());
lit.add("-------分隔符-------");
}
System.out.println("==========下面开始正向迭代===========");
lit=bookList.listIterator();//这里迭代器必须重新获得,经过上面迭代后,迭代器已经指向最后一个元素了。
while (lit.hasNext()) {
System.out.println(lit.next());
}
System.out.println("==========下面开始反向迭代===========");
while(lit.hasPrevious())
{
System.out.println(lit.previous());
}
输出结果:
程序说明:List通过ListTterator迭代集合时,即可采用next()方法进行正向迭代,迭代过程中可以使用add()方法向上一次迭代元素的后面添加一个新元素。同时程序演示了从后向前迭代。
2、ArrayList和Vector实现类
ArrayList和Vector作为List类的两个典型实现,完全支持前面介绍的List接口全部功能。
ArrayList和Vector类都是基于数组实现的List类,他们封装了一个动态再分配的Object[]数组。每个ArrayList或Vector对象有一个capacity属性,表示它们所封装的Object[]数组的长度。capacity会添加元素的个数而自动增加。当向集合中添加大量元素时,可以使用ensureCapacity方法一次性地增加capacity。这可以减少增加重分配次数,从而提供性能。capacity大小也可以在创建时就指定,该属性默认为10.
ArrayList和Vector提供如下两个方法来操作capacity属性:
void ensureCapacity(int minCapacity)
//:将ArrayList或Vector集合的capacity增加minCapacity。
void trimToSize()
//:调整ArrayList或Vector集合的capacity为列表当前大小。程序可
//调用该方法来减少ArrayList或Vector集合对象没有占用的存储空间。
ArrayList和Vector的区别:ArrayList和Vector用法几乎相同但是ArrayList是线程不安全的,多个线程访问同一个ArrayList集合时,如果有超过一条线程修改了ArrayList集合,则程序必须手动保证该集合的同步性。Vector集合则是线程安全的,不用另外保证该集合的同步性。因为Vector是线程安全的,所以Vector的性能比ArrayList的性能要低。实际上,即使保证List集合线程安全,同样不推荐使用Vector实现类。Collections工具类,可以将一个ArrayList变成线程安全的。
Vector还提供了一个Stack子类,它用于模拟了”栈“这种数据结构,”栈“通常是指”后进先出“(LIFO)的容器。最后”push“进栈的元素,将最先被”pop“出栈。与Java中其他集合一样,进栈出栈的都是Object,因此从栈中取出元素后必须做类型转换,除非你只是使用Object具有的操作。所以stack类提供了如下几个方法:
Object peek():返回”栈“的第一个元素,但并不将该元素”pop“出栈。
Object pop():返回”栈“的第一个元素,并将该元素”pop“出栈。
void push(Object item):将一个元素”push“进栈,最后一个进”栈“的元素总是位于”栈“顶。
例子
Stack<String> stack=new Stack<>();
stack.push("java");
stack.push("javaee");
stack.push("android");
stack.push("php");
System.out.println(stack);
System.out.println(stack.peek());
System.out.println(stack.pop());
System.out.println(stack);
输出结果
3、LinkedList实现类
List还有一个LinkedList的实现,它是一个基于链表实现的List类,对于顺序访问集合中的元素进行了优化,特别是当插入、删除元素时速度非常快,arraylist主要用于随机查询速度更快。因为LinkedList即实现了List接口,也实现了Deque接口(双向队列),Deque接口是Queue接口的子接口,它代表一个双向列表,Deque接口里定义了一些可以双向操作队列的方法: