Java集合之List接口


List接口继承了Collection接口,其主要实现类如下所示:

├List(在Collection接口的基础上新增加了一些方法)
│├LinkedList  (底层是链表实现)
│├ArrayList (底层为对象数组,容量默认为10,扩容1.5,即每次增长原来的0.5倍)
│ └Vector(底层为对象数组,容量默认为10,可按规定值扩容,默认为每次增长为原来的1倍)
│ └Stack


一、List接口常用实现类介绍

1、LinkedList类底层是由双链表实现的,双链表有一个虚拟节点header,节点值为null,前驱引用指向尾节点,后继引用指向头节点。通过虚拟节点header可很方便的找到尾节点,而不用去遍历整个链表。该类具有链表的所有特性,插入、删除操作很方便,访问节点需要遍历链表(虽然删除节点也需要遍历,但不需要移动元素)较慢。

    适用场景:数据的大小未知,数据动态插入与删除。

虚拟节点及其数据结构如下:

 private transient Entry<E> header = new Entry<E>(null, null, null);//虚拟节点

 private static class Entry<E> {
E element;
Entry<E> next;
Entry<E> previous;


Entry(E element, Entry<E> next, Entry<E> previous) {
   this.element = element;
   this.next = next;
   this.previous = previous;
}
    }

2、ArrayList类底层是由可变的对象数组实现的,对象数组默认大小为10,在容量不够时扩容为原来的1.5倍,即每次扩容大小增长0.5倍。ArrayList具有数组的所有性质,易于随机访问,一般情况下插入和删除需要移动元素(需要一定元素,扩容需要富足元素,代价较大)。

   适用场景:数据大小已知,高效访问,一般不需随机插入和删除。

 private transient Object[] elementData;//对象数组

//可以指定数组大小

 public ArrayList(int initialCapacity) {
super();
        if (initialCapacity < 0)
            throw new IllegalArgumentException("Illegal Capacity: "+
                                               initialCapacity);
this.elementData = new Object[initialCapacity];
    }


    /**
     * Constructs an empty list with an initial capacity of ten.
     */
    public ArrayList() {
this(10);
    }

//容量不够时做扩容处理,为原来大小的1.5倍,且需要将原来的元素复制到新的数组中,该过程较耗时。

 public void ensureCapacity(int minCapacity) {
modCount++;
int oldCapacity = elementData.length;
if (minCapacity > oldCapacity) {
   Object oldData[] = elementData;
   int newCapacity = (oldCapacity * 3)/2 + 1;
       if (newCapacity < minCapacity)
newCapacity = minCapacity;
            // minCapacity is usually close to size, so this is a win:
            elementData = Arrays.copyOf(elementData, newCapacity);
}
    }

3、Vector底层实现也是可变数组,其基本功能跟ArrayList类似,不同的是Vector是线程安全的,对象数组的操作全部加锁;另外其扩容大小为原来的2倍。由于加锁实现线程同步,访问效率比ArrayList慢。

   适用场景:数据大小已知,高效随机访问,且需要保证线程安全。

4、Stack继承自Vector,在Vector的基础上实现了元素先入后出的操作,线程安全。

    适用场景:数据大小已知,具有先入后出的特性。


二、其他知识点

1、结合排序

Java API针对集合类型排序提供了两种支持:
java.util.Collections.sort(java.util.List) 
java.util.Collections.sort(java.util.List, java.util.Comparator) 
第一个方法要求所排序的元素类必须实现java.lang.Comparable接口,该方法具有侵入性。
第二个方法要求实现一个java.util.Comparator接口。


2、集合遍历

 a、for each遍历

List<Integer> list = new ArrayList<Integer>();
for (Integer j : list) {
// use j
}

b、迭代器遍历

List<Integer> list = new ArrayList<Integer>();
for (Iterator<Integer> iterator = list.iterator(); iterator.hasNext();) {
iterator.next();
}

c、下标遍历

List<Integer> list = new ArrayList<Integer>();
for (int j = 0; j < list.size(); j++) {
list.get(j);
}

一般情况下建议使用for each遍历,勿须关注下标。迭代器遍历linkedList时,get方法会从头遍历至index下标,效率较低。


3、线程安全类

Collections.synchronizedList(List<? extends E> list)类是List的线程安全的代理类,在操作list时会加锁,线程安全。

Collections.UnmodifiableList(List<? extends E> list)类是List的线程安全类,只能读,不能写。




發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章