1. ArrayList、Vector、LinkedList三者的特点?ArrayList、Vector、LinkedList,分别在什么时候使用?
(1)看图:
从图中可以看出,LinkedList与ArrayList、ArrayDeque这三者都实现了List接口.所有使用方式也很相似,主要区别在于因为实现方式的不同,所以对不同的操作具有不同的效率。
(1)ArrayList是一个可改变大小的数组.当更多的元素加入到ArrayList中时,其大小将会动态地增长。内部的元素可以直接通过get与set方法进行访问,因为ArrayList本质上就是一个数组。
List arrayList = new ArrayList();
如果像上面这样使用默认的构造方法,初始容量被设置为10。当ArrayList中的元素超过10个以后,会重新分配内存空间,使数组的大小增长到16。可以通过调试看到动态增长的数量变化:10->16->25->38->58->88->…(增长幅度为:len/2 + 1)
(2)LinkedList是一个双链表,在添加和删除元素时具有比ArrayList更好的性能.但在get与set方面弱于ArrayList。
当然,这些对比都是指数据量很大或者操作很频繁的情况下的对比,如果数据和运算量很小,那么对比将失去意义。
(3)Vector和ArrayList类似,但属于强同步类。如果你的程序本身是线程安全的(thread-safe,没有在多个线程之间共享同一个集合/对象),那么使用ArrayList是更好的选择。
Vector和ArrayList在更多元素添加进来时会请求更大的空间。Vector每次请求其大小的双倍空间,而ArrayList每次对size增长50%。而LinkedList还实现了Queue接口,该接口比List提供了更多的方法,包括
offer(),peek(),poll()等。
注意: 默认情况下ArrayList的初始容量非常小,所以如果可以预估数据量的话,分配一个较大的初始值属于最佳实践,这样可以减少调整大小的开销。
LinkedList与ArrayList、ArrayDeque的实现机制完全不同,ArrayList、ArrayDeque内部以数组的形式来保存集合中的元素,因此随机访问集合元素时有较好的性能;而LinkedList内部以链表的形式来保存集合中的元素,因此随机访问集合元素时性能较差,但在插入、删除元素时性能非常出色(只需改变指针所指的地址即可)。
如果需要遍历List集合元素,对于ArrayList、Vector集合,应该使用随机访问方法(get)来遍历集合元素,这样性能更好;对于LinkedList集合,则应该采用迭代器(Iterator)来遍历集合元素;
如果需要经常执行插入、删除操作来改变List集合的大小,则应该使用LinkedList集合,而不是ArrayList。使用ArrayList、Vector集合需要经常重新分配内部数组的大小,其时间开销往往是使用LinkedList的几十倍,效果更差;
如果有多个线程需要同时访问List集合中的元素,开发者可考虑使用Collections工具类将集合包装成线程安全的集合。
Collection:
public boolean add(E e)
public boolean addAll(Collection c)
public void clear()
public boolean remove(Object o)
public boolean removeAll(Collection c)
public boolean contains(Object o)
public boolean containsAll(Collection c)
public boolean isEmpty()
public Iterator<E> iterator()
public boolean retainAll(Collection<?> c)
public int size()
public Object[] toArray()
List:
public void add(int index, Object element)
public Object remove(int index)
public Object set(int index, Object element)
public Object get(int index) 返回列表中指定位置的元素。
public ListIterator listIterator() 列表迭代器(List集合特有的迭代器)
2. 集合的遍历
a)把集合转换成数组后遍历
b)使用迭代器进行遍历
请编写程序,存储3个学生对象到List集合中,
a)使用迭代器进行遍历
b)使用size()和get()方法结合进行遍历
c)使用列表迭代器进行遍历
public class MainDemo {
@Test
public void test(){
//demo1();
demo2();
}
public void demo1(){
Student[] students = {
new Student(1, "John"),
new Student(2, "Mary"),
new Student(3, "Tom"),
new Student(4, "Lucy")
};
for (int i = 0; i < students.length; i++) {
System.out.println(students[i]);
}
}
public void demo2(){
List<Student> students = new ArrayList();
students.add(new Student(1, "John"));
students.add(new Student(2, "Mary"));
students.add(new Student(3, "Tom"));
students.add(new Student(4, "Lucy"));
Object[] array = students.toArray();
for (int i = 0; i < array.length; i++) {
System.out.println(array[i]);
}
for (int i = 0; i < students.size(); i++) {
System.out.println(students.get(i));
}
for (ListIterator i = students.listIterator(); i.hasNext(); ) {
System.out.println(i.next());
}
Iterator<Student> iterator = students.iterator();
while (iterator.hasNext()){
System.out.println(iterator.next());
}
for (Student student : students) {
System.out.println(student);
}
}
}