前言
昨天无意间翻看自己的博客列表的时候才发现,集合部分的总结居然还有List的一部分没有记录,真是大意了。于是立刻翻出之前的读书笔记,稍作整理,今天特意来补上这部分。学习的事,无论大小都还是要有头有尾。
List摘要
List在存储元素的实现机制上,于Map和Set有很大的区别。List集合在添加元素时按照元素的添加顺序设置元素的索引,从0开始。因此List集合的元素时有序的,正因为其有序性,我们在取元素的时候可以根据索引精确到每一个元素,所以元素间是否重复就对元素的唯一性没有太大的影响了。通过这个特征,我们就可以轻松的记忆,List集合代表一个元素有序、可重复的集合。
List的equals()方法
之前在讲HashMap的时候,提到过判断集合内元素间是否相等,需要equals()和hashCode()协同作业。List由于其集合内元素的有序不重复性,在作等价判断时就简单许多。List判断两个对象相等的标准是,只要两个对象通过equals()方法比较返回true,那么这两个元素就是相等的。
通过List实现队列操作
在之前的笔试经历中,遇到过这个问题,当时就想到了上面说的这点。通过重写对象的equals()方法,让其每次都返回true。List在调用remove()方法从集合中删除一个重写了equals()方法的对象时,由于每次返回true,所以List每次都是删除集合中的第一个元素,模拟了队列的出列操作。
package list;
import java.util.ArrayList;
import java.util.List;
class A{
public boolean equals(Object obj){
return true;
}
}
public class ListTest {
public static void main(String[] args) {
List<String> war3Player = new ArrayList<String>();
war3Player.add("sky");
war3Player.add("lyn");
war3Player.add("moon");
System.out.println(war3Player);
//出列
war3Player.remove(new A());
System.out.println(war3Player);
//出列
war3Player.remove(new A());
System.out.println(war3Player);
}
}
运行结果如下所示:
ArrayList和Vector
每个集合都有其线程安全和非线程安全实现子类,List也不例外。
- 非线程安全:ArrayList
- 线程安全:Vector
ArrayList和Vector作为List的两个经典实现,自然完全支持List接口的全部功能,他们都是基于数组实现的List类,所以ArrayList和Vector封装了一个动态的、允许再分配的Object[]数组。它们都有initialCapacity参数来设置数组的长度,当ArrayList和Vector中添加的元素超出了数组的原先长度时,它们的initialCapacity参数会自动增加。
有一点要提的是,由于Vector和hashtable一样,是一个很古老的集合,也有很多类似addElement的长命名方法(其实和add方法没有任何区别),方法上有功能重复,所以Vector在实际应用中有许多上古遗留下来的缺点,我们应该尽量避免使用它们。那么就有人会问,那我们需要线程安全的List对象该怎么办呢?可以参照之前几篇集合归纳说的,通常可以使用Collections工具类的Synchronized…装饰符去创建一个线程安全的List,如下:
Collection collection = Collections.synchronizedCollection(new ArrayList());
或者
List list = Collections.synchronizedList(new ArrayList());
ArrayList和LinkedList
ArrayList和LinkedList实现的机制完全不同,ArrayList在上面说了,它的内部是以数组的形式来保存集合中的元素,因此随机访问集合中元素时有较好的性能;而LinkedList内部以链表的形式来保存集合中元素,因此随机访问LinkedList中的元素时性能较差,但在插入、删除元素时性能较为出色,只需要改变指针所指向的前一个和后一个节点的地址即可。
通过上面说的,我们可以做一个总结:
如果需要遍历List的集合元素,对于ArrayList和Vector,应该使用随机访问的方法(get)来遍历集合元素;对于LinkedList,则应当使用迭代器Iterator来遍历集合元素。