List集合知識總結

轉載:java

一:集合的概念程序員

集合:保存數量不肯定的數據,以及保存具備映射關係的數據的容器,簡單的理解就是用於存儲數量不等的多個對象的容器。算法

集合和數組不同,數組元素既能夠是基本類型的值,也能夠是對象(對象的引用變量);而集合裏只能保存對象(對象的引用變量)。編程

Java集合類主要由兩個集合框架的根接口派生而出:Collection和Map數組

Java中Collection接口的體系機構:安全

Collection接口和Iterator接口:數據結構

Collection接口是List、Set和Queue接口的父接口,該接口中定義了一些操做集合元素的方法:框架

下面列舉一些常見的方法:ide

boolean add(Object o):該方法用於向集合裏添加一個元素。函數

boolean addAll(Collection c):該方法把集合c裏的全部元素添加到指定的集合裏。

void clean():清除集合裏的全部元素,將集合長度變爲0。

boolean contains():返回集合裏是否包含指定元素。

boolean containsAll():返回集合裏是否包含集合c裏的全部元素。

boolean isEmpty():返回集合是否爲空。當集合長度爲0時返回true,不然返回false。

Iterator iterator():返回一個Iterator對象,用於遍歷集合中的元素。

boolean remove(Object o):刪除集合中指定的元素o,當集合中包含了一個或多個元素o時,這些元素將被刪除,該方法將返回true。

boolean removeAll(Collection c):從集合中刪除集合c裏包含的全部元素。

boolean retainAll(Collection c):從集合中刪除集合c裏不包含的元素(至關於取得把調用該方法的集合變爲該集合和集合c的交集),若是該操做改變了調用該方法的集合,返回true。

int  size():該方法返回集合裏元素的個數。

Object[]  toArray():該方法把集合轉換成一個數組,全部集合元素變成對應的數組元素。

Iterator接口:

Iterator接口也是Java集合框架的成員,但它與Collection系列、Map系列的集合不同:Collection系列集合和Map系列的集合主要用於盛裝其餘對象,而Iterator則主要用於遍歷集合的元素。又叫迭代器。

Iterator接口隱藏了各類Collection實現類的底層細節,只嚮應用程序提供遍歷集合元素的統一編程接口。

Iterator接口定義了三個方法:

boolean hasNext():若是被迭代的集合元素還有沒遍歷,則返回true。

Object next():返回集合裏的下一個元素。

void remove():刪除集合裏上一次next方法返回的元素。

Iterator僅用於遍歷集合,若是須要建立Iterator對象,則必須有一個被迭代的集合。沒有集合和Iterator彷彿無本之木,沒有存在的意義。

當使用Iterator對集合元素進行迭代時,Iterator並非把集合元素本事傳給了迭代變量,而是把集合元素的值傳給了迭代變量,因此修改迭代變量的值對集合元素本事沒有影響。

當使用Iterator來迭代訪問Collection集合元素時,Collection集合裏的元素不能被修改,只能經過remove方法刪除上次next方法返回的集合元素才能夠,不然報java.util.ConcurrentModificationException異常。

Iterator迭代器採用的是快速失敗(fail-fast)機制,一旦在迭代過程當中檢測到該集合已經被修改(一般是其餘線程進行修改),程序將報java.util.ConcurrentModificationException異常。而不是顯示修改後的結果,這樣能夠避免共享資源而引起的問題。

foreach循環變量集合元素

格式:

for(類型   新對象:集合){

用法和Iterator相似。

二:Set接口

Set集合是無順序的,其集合元素不容許重複。

Set集合判斷兩個對象相同不是使用==運算符,而是根據equals方法。簡單的說,若是隻要兩個對象用equals方法比較返回true,Set集合就不會接受這兩個對象;反之,則成立。

HashSet類:

HashSet是Set集合的實現類,HashSet按Hash算法來存儲集合中的元素,所以具備很好的存取和查找性能。

HashSet集合特色:

(1)不能保證元素的排列順序,順序有可能發生變化。

(2)HashSet不是同步的,若是多個線程同時訪問一個HashSet,若是有2條或2條以上線程同時修改HashSet集合時,必須經過代碼實現線程同步。

(3)集合元素值能夠是null。

向HastSet集合中存入一個元素時,HashSet會調用該對象的hashCode()方法來獲得該對象的hashCode值,而後根據該HashCode值來決定該對象在HashSet中存儲位置。若是有兩個元素經過equals方法比較返回true,但它們的hashCode()方法返回值不相等,HashSet將會把它們存儲在不一樣的位置,就能夠添加成功(簡單的理解HastSet集合判斷兩個元素是否相等的標準是兩個對象經過equals方法比較相等,且兩個對象的hashCode()方法返回的值也要相等)。

TreeSet類:

TreeSet是SortedSet接口的惟一實現,TreeSet能夠確保集合元素處於排序狀態。

TreeSet新添的方法:

(1)Comparator  comparator():返回當前Set使用的Comparator,或者返回null,表示以天然方式排序。

(2)Object  first():返回集合中的第一個元素。

(3)Object  last():返回集合中的最後一個元素。

(4)Object  lower(Object e):返回集合中位於指定元素以前的元素。

(5)Object  higher(Object e):返回集合中位於指定元素以後的元素。

(6)SortedSet  subSet(fromElement,toElement):返回此Set的子集合,範圍衝fromElement(包含)到toElement(不包含)。

(7)SortedSet  headSet(toElement):返回此Set的子集,由小於toElement的元素組成。

(8)SortedSet  tailSet(fromElement):返回此Set的子集,由大於或等於fromElement的元素組成。

TreeSet集合並非根據元素的插入順序進行排序,而是根據元素實際值進行排序。

TreeSet集合採用紅黑樹的數據結構對元素進行排序。TreeSet集合支持兩種排序方法:天然排序和定製排序。默認使用天然排序。

天然排序

TreeSet調用集合元素的compareTo(Object obj)方法來比較元素之間大小關係,而後將集合元素按升序排列,這就是天然排序。

Java提供了一個Comparable接口,該接口裏定義了一個compareTo(Object obj)方法,該方法返回一個整數,實現該接口的類必須實現該方法,當一個對象調用該方法與另外一個對象進行比較時,好比:obj1.compareTo(obj2),若是該方法返回0,則代表兩個對象相等,若是返回是一個正整數,則代表obj1大於obj2,若是返回是一個負數,則代表obj1小於obj2。

注意:向TreeSet集合中添加元素時,只有第一個元素能夠不實現Comparable接口,後面添加的全部元素都必須實現Comparable接口。不然報ClassCastException異常。

當把一個對象加入TreeSet集合中時,TreeSet調用該對象的compareTo方法與集合中的其餘對象比較大小,而後根據紅黑樹算法決定它存儲的位置。若是兩個對象相等,TreeSet將把他們存儲在同一位置。TreeSet集合比較兩個對象相等的標準是:兩個對象經過equals方法返回true,或經過compareTo方法比較返回0,則認爲兩個對象是同一個對象。

定製排序

經過實現Comparator接口中的compare方法來實現集合的定製排序,

int   compare(T o1,T o2)方法比較大小,若是返回是正整數,則代表o1大於o2,若是返回0,則代表兩個對象相等,若是返回負數,則代表o1小於o2。

若是須要實現定製排序,則須要在建立TreeSet集合對象時,並提供一個Comparator對象與該集合關聯,由該Comparator對象負責集合的排序邏輯。

經典實例

public class TreeSetTest {
 
    public static void main(String[] args) {
        //定義TreeSet集合,併爲集合提供一個排序的Comparator對象(這裏是匿名內部類)。
        TreeSet<M> ts = new TreeSet<M>(new Comparator<M>() {
            @Override
            public int compare(M m1, M m2) {
                // TODO Auto-generated method stub
                if (m1.num > m2.num) {
                    return -1;//這是按降序排序,若是想按升序排序,這裏返回正整數,下面else中返回負數,便可。
                } else if (m1.num == m2.num) {
                    return 0;
                } else {
                    return 1;
                }
            }
        });
        //向集合中添加數據
        ts.add(new M(5));
        ts.add(new M(-3));
        ts.add(new M(8));
        ts.add(new M(6));
        System.out.println(ts);
 
    }
}
 
class M {
    // 定義一個變量
    int num;
 
    public M(int num) {
        // 構造函數中爲變量賦值
        this.num = num;
    }
 
    // 重寫toString方法
    public String toString() {
        return "M對象num的值爲" + this.num;
    }
}

EnumSet類
EnumSet類是一個專爲枚舉類設計的集合類,EnumSet中全部的元素都必須是指定枚舉類型的枚舉值,該枚舉類型在建立EnumSet時顯式或隱式地指定。EnumSet的集合元素也是有序的,EnumSet以枚舉值在Enum類內的定義順序來決定集合元素的順序。EnumSet集合不容許插入null元素。

EnumSet集合的內部一位向量的形式存儲,這種存儲形式很是緊湊、高效,所以EnumSet對象佔用內存很小,並且運行效率很好。具體體如今批量操做集合時。

EnumSet類沒有暴露任何構造函數來建立該類的實例,程序經過它提供的static方法來建立EnumSet對象。

EnumSet集合經常使用的方法

(1)static EnumSet  allOf(Class elementType):建立一個包含指定枚舉類裏全部枚舉值的EnumSet集合。

(2)static EnumSet  complementOf(EnumSet s):建立一個其元素類型與指定EnumSet裏元素類型相同的EnumSet,新EnumSet集合包含原EnumSet集合所不包含的、此枚舉類剩下的枚舉值。

(3)static EnumSet  copyOf(Collection c):使用一個普通集合來建立EnumSet集合。

(4)static EnumSet  copyOf(EnumSet s):建立一個與指定EnumSet具備相同元素類型、相同集合元素的EnumSet。

(5)static EnumSet  noneOf(Class elementType):建立一個元素類型爲指定枚舉類型的空EnumSet。

(6)static EnumSet  of(E first,E...rest):建立一個包含一個或多個枚舉值的EnunSet,傳入的多個枚舉值必須屬於同一個枚舉類。

(7)static EnumSet  range(E from,E to):建立包含從from枚舉值,到to枚舉值範圍內全部枚舉值的EnumSet集合。

經典實例:

public class EnumSetTest {
 
    public static void main(String[] args) {
        EnumSet<Season> es=EnumSet.allOf(Season.class);
        System.out.println(es);//打印[SPRING, SUMMER, FAILL, WINTER]
        EnumSet<Season> es1=EnumSet.of(Season.SPRING,Season.SUMMER,Season.WINTER);
        System.out.println(es1);//打印[SPRING, SUMMER, WINTER]
        EnumSet<Season> es2=EnumSet.range(Season.SUMMER, Season.WINTER);
        System.out.println(es2);//打印[SUMMER, FAILL, WINTER]
        EnumSet<Season> es3=EnumSet.complementOf(es2);
        System.out.println(es3);//打印[SPRING]
    }
}
 
enum Season{
    SPRING,SUMMER,FAILL,WINTER
}

總結
HashSet和TreeSet是Set的兩個典型實現,HashSet的性能總比TreeSet好(添加,查詢操做),由於TreeSet須要額外的紅黑樹算法來維護集合元素的次序。TreeSet是有序的集合。

HashSet還有一個子類LinkedHashSet,對於普通的插入,刪除操做,LinkedHashSet比HashSet要慢一點點,這是由於維護鏈表所帶來的開銷。不過遍歷集合時,LinkedHashSet就很是塊 。

EnumSet是全部Set實現類中性能最好 ,但它只能保存同一個枚舉類的枚舉值做爲集合元素。

注意:Set的三個實現類HashSet 、TreeSet、EnumSet都是線程不安全的。若是有多條線程同事訪問一個Set集合,而且有超過一條線程修改集合的值,則必須手動保證集合的同步性,不然將沒法訪問修改後的集合。

List接口

List集合表明一個有序的集合 ,集合中每一個元素都有其對應的順序索引。List集合容許使用重複元素,經過索引來訪問指定位置的集合元素。

List集合在Collection的基礎上新添加的方法:

(1)void  add (int index,Object element):將元素element插入在List集合的index處。

(2)boolean  addAll(int index,Collection c):將集合c所包含的全部元素都插入在List集合的Index處。

(3)Object  get(int index):返回集合index索引處的元素。

(4)int  indexOf(Object o):返回對象o在List集合中出現的位置索引。

(5)int  lastIndexOf(Object o):返回對象o在List集合中最後一次出現的位置索引。

(6)Object  remove(int index):刪除並返回index索引處的元素。

(7)Object  set(int index,Object element):將index索引處的元素替換成element對象,返回新元素。

(8)List subList(int fromIndex,int toIndex):返回從索引fromIndex(包含)到索引toIndex(不包含)處全部集合元素組成的子集合。

ListIterator接口:

ListIterator接口是Iterator的子接口,提供了專門操做List的方法。

ListIterator接口新增的方法:

(1)boolean  hasPrevious():返回該迭代器關聯的集合是否還有上一個元素。

(2)Object  previous():返回該迭代器的上一個元素。

(3)void  add():在指定位置插入一個元素。

根據上面的三個方法和解釋,不難發現ListIterator新增長了向前迭代的功能,並且ListIterator還能夠經過add方法向List集合中添加元素。

經典實例:

public class ListTest {
 
    public static void main(String[] args) {
        List<String> list = new ArrayList<String>();
        list.add("smarhit");
        list.add("heima");
        list.add("sichuan");
        list.add("chengdu");
        ListIterator<String> lit = list.listIterator();
        while (lit.hasNext()) {
            System.out.print(lit.next()+"\t");
        }
        System.out.println("\n----------開始反向迭代--------------");
        while (lit.hasPrevious()) {
            System.out.print(lit.previous()+"\t");
        }
        /*
         * 打印的結果是:
         * smarhit heima sichuan chengdu
         *  ----------開始反向迭代--------------
         * chengdu sichuan heima smarhit
         */
 
    }
}

ArrayList和Vector實現類
ArrayList和Vector類都是基於數組實現的List類,ArrayList和Vector類封裝了一個動態在分配的Object[ ]數組。每一個ArrayList或Vector對象有一個capacity屬性,該屬性表示他們所封裝的數組的長度,當想ArrayList或Vector中添加元素時,它們的capacity會自動增長。對於一般編程中,程序員無須關心ArrayList或Vector的capacity屬性。但若是向ArrayList集合或Vector集合中添加大量元素時,可以使用ensureCapacity方法一次性的增長capacity。這樣能夠提升性能。

ArrayList和Vector在用法上幾乎徹底相同(Vector是古老的集合,JDK1.0就存在了),但ArrayList集合是線程不安全的,當多條線程訪問同一個集合時,若是有超過一條線程修改了ArrayList集合,則程序必須手動保證該集合的同步性。而Vector集合則是線程安全的。無須程序保證集合的同步性。因此Vector的性能比ArrayList的性能低。

Vector還提供了一個Stack子類,它用於模擬了「棧」這中數據結構,「棧」一般是指「後進先出」的容器。最後「push」進棧的元素,將最早被「pop」出棧。

Stack類提供的方法:

(1)Object  peek():返回「棧」的第一個元素,但並不將該元素"pop"出棧。

(2)Object  pop():返回"棧"的第一個元素,並將該元素"pop"出棧。

(3)void  push(Object item):將一個元素「push」進棧,最後一個進「棧」的元素老是位於「棧」頂。

經典實例:

public class StackTest {
    
    public static void main(String[] args) {
        Stack<String> s=new Stack<String>();
        s.push("smarhit");
        s.push("beijin");
        s.push("neijiang");
        s.push("chengdu");
        System.out.println(s);//打印[smarhit, beijin, neijiang, chengdu]
        System.out.println(s.peek());//打印chengdu
        System.out.println(s);//打印[smarhit, beijin, neijiang, chengdu]
        System.out.println(s.pop());//打印chengdu
        System.out.println(s);//打印[smarhit, beijin, neijiang]
    }
}

固定長度的List
數組的工具類 Arrays提供的asList()方法是把一個數組或指定個數的對象轉換成一個List集合, 但這個List集合既不是ArrayList實現類的實例,也不是Vector實現類的實例,而是Arrays的內部類ArrayList實例。Arrays.ArrayList是一個固定長度的List集合,程序只能遍歷訪問該集合裏的元素,不可增長,刪除該集合中的元素。


Queue接口

Queue模擬了隊列這中數據結構,隊列一般是"先進先出"的容器。

Queue接口提供的方法:

(1)void  add(Object e):將指定元素加入此隊列的尾部。

(2)Object  element():獲取隊列頭部的元素,但不是刪除該元素。

(3)boolean  offer(Object e):將指定元素加入此隊列的尾部。當使用有容器限制的隊列時,此方法一般比add(Object e)方法更好。

(4)Object  peek():獲取隊列頭部的元素,可是不刪除該元素。若是此隊列爲空,則返回null。

(5)Object  poll():獲取隊列頭部的元素,並刪除該元素。若是此隊列爲空,則返回null。

(6)Object  remove():獲取隊列頭部元素,並刪除該元素。

LinkedList實現類:

LinkedList類是一個比較特殊的類,它實現了List接口,還實現了Deque接口,Deque接口是Queue接口的子接口,它表明一個雙向隊列。

LinkedList類提供的方法:

(1)void  addFirst(Object e):將指定元素插入該雙向隊列的開頭。

(2)void addLast(Object e):將指定元素插入該雙向隊列的尾部。

(3)Iterator descendingIterator():返回以該雙向隊列對應的迭代器,該迭代器將以逆向順序來迭代隊列中的元素。

(4)Object  getFirst():獲取、但不刪除雙向隊列的第一個元素。

(5)Object  getLast():獲取、但不刪除雙向隊列的最後一個元素。

(6)boolean  offerFirst(Object e):將指定的元素插入該雙向隊列的開頭。

(7)boolean  offerLast(Object e):將指定的元素插入該雙向隊列的尾部。

(8)Object   peekFirst():獲取、但不刪除該雙向隊列的第一個元素;若是此雙向隊列爲空,則返回null。

(9)Object   peekLast():獲取、但不刪除該雙向隊列的最後一個元素;若是此雙向隊列爲空,則返回null。

(10)Object  pollFirst():獲取、並刪除該雙向隊列的第一個元素;若是此雙向隊列爲空,則返回null。

(11)Object  pollLast():獲取、並刪除該雙向隊列的最後一個元素;若是此雙向隊列爲空,則返回null。

(12)Object  pop():pop出該雙向隊列所表示的棧中第一個元素。

(13)void  push(Object e):將一個元素push進該雙向隊列所表示的棧中。

(14)Object  removeFirst():獲取、並刪除該雙向隊列的第一個元素。

(15)Object  removeFirstOccurrence(Object o):刪除該雙向隊列的第一個出現元素o。

(16)removeLast():獲取、並刪除該雙向隊列的最後一個元素。

(17)removeLastOccurrence(Object  o):刪除該雙向隊列的最後一次出現元素o。

總結:LinkedList與ArrayList、Vector的實現機制徹底不一樣。ArrayList、Vector內部以數組的形式來保存集合中的元素,所以隨機訪問集合元素上有較好的性能;而linkedList內部以鏈表的形式來保存集合中的元素,所以隨機方法集合元素時性能較差,但在插入、刪除元素時性能很是出色(只需改變指針所指的地址便可)。

PriorityQueue實現類

PriorityQueue是一個比較標準的隊列實現類,PriorityQueue保存隊列元素的順序並非按加入隊列的順序,而是按隊列元素的大小進行從新排序。

PriorityQueue不容許插入null元素,它須要對隊列元素進行排序。

排序的方式:天然排序,定製排序。

上面是對List集合的詳解總結。在開發過程當中,咱們可能只運用到一些常見的結合,但其餘集合也應作相應的瞭解。

相關文章
相關標籤/搜索