1. 程式人生 > >Collection集合總結

Collection集合總結

Collection介面繼承體系圖

 Collection介面常用方法

返回值型別 方法     解釋
boolean add(E e) 向列表的尾部新增指定的元素(可選操作)
boolean addAll(Collection<? extends E> c) 將指定 collection 中的所有元素都新增到此 collection 中(可選操作)
void clear() 移除此 collection 中的所有元素(可選操作)
boolean contains(Object o) 判斷集合是否包含此元素,包含返回true
boolean equals(Object o) 比較此 collection 與指定物件是否相等
int hashCode() 返回此 collection 的雜湊碼值
boolean isEmpty() 如果此 collection 不包含元素,則返回 true
Iterator<E>  iterator() 返回在此 collection 的元素上進行迭代的迭代器
boolean remove(Object o) 刪除第一次出現在集合的指定元素,返回值為被刪除的元素(如果存在)
int size() 返回列表中的元素數
Object[] toArray() 返回按適當順序包含列表中的所有元素的陣列(不常用)

一、List集合

List 就是列表的意思,它是Collection 的一種,即繼承了 Collection 介面,以定義一個允許重複項的有序集合。該介面不但能夠對列表的一部分進行處理,還添加了面向位置(索引)的操作。List 是按物件的進入順序進行儲存物件,而不做排序或編輯操作。它除了擁有Collection介面的所有的方法外還擁有一些其他的方法。
面向位置(索引)的操作包括插入某個元素或 Collection 的功能,還包括獲取、除去或更改元素的功能。在 List 中搜索元素可以從列表的頭部或尾部開始,如果找到元素,還將報告元素所在的位置。

List介面子實現類的特點

  • ArrayList:底層結構是陣列,增刪慢,查詢快(執行緒不安全,效率高)
  • Vector:底層結構是陣列,增刪,查詢都很慢(執行緒安全,因此查詢效率比ArrayList要低)
  • LinkedList:內部是連結串列資料結構,,增刪元素的速度很快(執行緒不安全)

List集合特有的常用方法

返回值型別 方法     解釋
boolean addAll(Collection<? extends E> c) 按照迭代器返回的元素順序,將指定集合插入到指定集合中
boolean addAll(int index, Collection<? extends E> c) 從指定的位置開始,將指定 collection 中的所有元素插入到此列表中
E get(int index) 返回列表中指定位置的元素
int indexOf(Object o) 返回該元素第一次出現在集合中的索引值;若不包含該元素,則返回 -1
int lastIndexOf(Object o) 返回該元素最後一次出現在集合中的索引值;若不包含該元素,則返回 -1
ListIterator<E> listIterator() 返回此列表元素的列表迭代器(按適當順序)
E remove(int index) 根據索引刪除元素,返回值為被刪除的元素
E set(int index, E element)  根據索引,修改集合中的元素,返回值為替換前的元素

常用方法演示

    public void test01() {
        ArrayList<String> list = new ArrayList<>();
        list.add("三國演義");
        list.add("西遊記");
        list.add("水滸傳");
        list.add("紅樓夢");
        Iterator<String> ite = list.iterator();
        while (ite.hasNext()) {
            String next = ite.next();
            // 判斷當前元素是否是"西遊記"
            if (next.equals("西遊記")) {
                // 根據索引修改當前元素為 "吳承恩"
                list.set(list.indexOf(next), "吳承恩");
            }
            // 輸出結果:三國演義	西遊記	水滸傳	紅樓夢
            System.out.print(next + "\t");
        }
        System.out.println();
        // 將集合list轉換成Object陣列
        Object[] arr = list.toArray();
        for (int i = 0; i < arr.length; i++) {
            String str = (String) arr[i];
            // 輸出結果:三國演義	吳承恩	水滸傳	紅樓夢
            System.out.print(str + "\t");
        }
    }

注意:集合中的元素必須是物件,不能是基本資料型別(JDK 1.5後提供自動拆裝箱)

Collection集合的remove(obj)方法和Iterator介面中的remove()方法的使用

    public void test02() {
        List<String> list1 = new ArrayList<>();
        List<String> list2 = new ArrayList<>();
        list1.add("三國演義");
        list1.add("西遊記");
        list1.add("水滸傳");
        list1.add("紅樓夢");
        Iterator<String> ite = list1.iterator();
        while (ite.hasNext()) {
            String next = ite.next();
            // 判斷當前元素是否是"西遊記"
            if (next.equals("西遊記")) {
                // 移除當前元素"西遊記"
                //list.remove(next); //報錯,併發修改異常ConcurrentModificationException
                // 使用Iterator的方法移除元素不會報錯
                ite.remove();
            }
        }
        list2.addAll(list1);
        System.out.println("list1 = " + list1);// list1 = [三國演義, 水滸傳, 紅樓夢]
        System.out.println("list2 = " + list2);// list2 = [三國演義, 水滸傳, 紅樓夢]
    }

注意:迭代器遍歷集合時,使用Collection集合的remove(obj)方法會報併發修改異常java.util.ConcurrentModificationException,

但使用Iterator介面中的remove()方法,程式執行正常。

出現異常 java.util.ConcurrentModificationException的原因及解決辦法?

原因:在迭代過程中,使用了List集合的方法對元素進行操作。導致迭代器並不知道集合中的變化,容易引發資料的不確定性

解決辦法:

  • 在迭代時,不要使用集合的方法操作元素
  • 使用普通的for迴圈遍歷集合
  • 使用ListIterator迭代器操作元素,解決了使用Iterator迭代過程中可能會發生的錯誤情況(後面會講)

1.1、ArrayList集合特點及方法

特點:資料儲存的結構是陣列結構。元素增刪慢,查詢快,由於日常開發中使用最多的功能為查詢資料、遍歷資料,所以ArrayList是最常用的集合。

常用方法:全部繼承自List介面

1.2、LinkedList集合的特點及方法

特點:資料儲存的結構是連結串列結構。元素增刪快,查詢慢。實際開發中對一個集合元素的新增與刪除經常涉及到首尾操作,而LinkedList提供了大量首尾操作的方法

常用方法:

返回值型別 方法     解釋
void addFirst(E e) 將指定元素插入此列表的開頭
void addLast(E e) 將指定元素新增到此列表的結尾 
E getFirst()  返回此列表的第一個元素(連結串列為空,丟擲NoSuchElementException)
E getLast() 返回此列表的最後一個元素
E removeFirst() 移除並返回此列表的第一個元素
E removeLast() 移除並返回此列表的最後一個元素
E peekFirst() 獲取但不移除此列表的第一個元素(連結串列為空,返回null)
E pollFirst() 獲取但不移除此列表的第一個元素(列表為空,返回 null)

利用LinkedList集合特點模擬一個堆疊或者佇列資料結構

堆疊:先進後出 First In Last Out

佇列:先進先出 First In First Out

   /**
     * 利用LinkedList集合特點模擬一個堆疊
     * 堆疊:先進後出 First In Last Out
     */
    @Test
    public void test05() {
        LinkedList<String> lklist = new LinkedList<>();
        lklist.addLast("one");
        lklist.addLast("two");
        lklist.addLast("three");
        lklist.addLast("four");
        lklist.addLast("five");
        Iterator<String> ite = lklist.iterator();
        while (ite.hasNext()) {
            String next = ite.next();
            System.out.print(next + " ");// one two three four five
        }
    }

    /**
     * 利用LinkedList集合特點模擬佇列資料結構
     * 佇列:先進先出 First In First Out
     */
    @Test
    public void test06() {
        LinkedList<String> lklist = new LinkedList<>();
        lklist.addFirst("one");
        lklist.addFirst("two");
        lklist.addFirst("three");
        lklist.addFirst("four");
        lklist.addFirst("five");
        Iterator<String> ite = lklist.iterator();
        while (ite.hasNext()) {
            String next = ite.next();
            System.out.print(next + " "); // five four three two one
        }
    }

1.3、Vector集合的特點及方法(被ArrayList取代)

特點:資料儲存的結構是陣列結構,為JDK中最早提供的集合。Vector集合已被ArrayList替代。列舉Enumeration已被迭代器Iterator替代。

常用方法:

返回值型別 方法     解釋
void addElement(E obj) 將指定的元件新增到此向量的末尾,將其大小增加 1
E elementAt(int index)  返回指定索引處的元件
Enumeration<E> elements() 返回此向量的元件的列舉

Vector集合對ArrayList集合使用的對比

二、Set介面

Java 中的Set和正好和數學上直觀的集(set)的概念是相同的。Set最大的特性就是不允許在其中存放的元素是重複的。根據這個特點,我們就可以使用Set 這個介面來實現前面提到的關於商品種類的儲存需求。Set 可以被用來過濾在其他集合中存放的元素,從而得到一個沒有包含重複新的集合。

Set介面中的方法和Collection一致,這裡就不列出了

Set介面子實現類的特點

  • HashSet:內部資料結構是雜湊表(執行緒不安全)
  • LinkHashSet:內部資料結構是連結串列和雜湊表(執行緒不安全)
  • TreeSet:內部資料結構是平衡樹(Balanced tree),元素唯一、有序(執行緒不安全)

重寫hashCode()、equals()方法,保證Set集合元素唯一性,原始碼判斷步驟如下

①判斷的是兩個元素的雜湊值是否相同,即hashCode()

如果雜湊值不同,不需要判斷equals(),就可以保證元素的唯一了

如果相同,再判斷兩個物件的內容是否相同,即equals()

注意:hashCode()方法判斷物件的雜湊值是否相同;equals()方法判斷內容是否相同

注意:HashSet儲存JavaAPI中提供的型別元素時,不需要重寫元素的hashCode()和equals()方法,因為這兩個方法,在JavaAPI的每個類中已經重寫,如String類、Integer類等,但是自定義類需要自己重寫hashCode()和equals()方法,否則無法保證元素唯一性。

下面程式碼體現了Set集合的唯一性

    /**
     * 利用Set集合元素唯一性移除List集合中重複元素
     * String類已經重寫hashCode()和equals()方法
     */
    @Test
    public void test03() {
        Collection<String> set = new HashSet<>();
        Collection<String> list = new ArrayList<>();
        for (int i = 5; i > 0; i--) {
            list.add(i + "");
        }
        list.add("1");
        list.add("3");
        list.add("5");
        System.out.println("list = " + list);// 輸出結果:list = [5, 4, 3, 2, 1, 1, 3, 5]
        set.addAll(list);
        System.out.println("set = " + set);// 輸出結果:set = [1, 2, 3, 4, 5]
    }

疑惑:set = [1, 2, 3, 4, 5]的輸出結果有點疑惑,set集合自動將結果排序了,查看了下Integer類實現了Comparable介面

2.1、HashSet的特點及方法

特點:資料儲存的結構是雜湊表。元素存取無序,集合元素唯一,元素並不是按照存入時的順序(和List顯然不同) 是按照雜湊值確定存放在HashSet集合的位置,因此也是按照雜湊值取資料的

常用方法:全部實現自Set介面

2.2、LinkHashSet的特點及方法

特點:連結串列和雜湊表組合的一個數據儲存結構,因此元素存取有序、且保證元素唯一性

常用方法:全部實現自Set介面

    public void test07() {
        Set<String> set = new LinkedHashSet<String>();
        set.add("三國演義");
        set.add("西遊記");
        set.add("水滸傳");
        set.add("紅樓夢");
        set.add("西遊記");
        set.add("三國演義");
        Iterator it = set.iterator();
        while (it.hasNext()) {
            System.out.print(it.next() + "\t");// 三國演義  西遊記  水滸傳  紅樓夢
        }

    }

2.3、TreeSet的特點及方法

特點:TreeSet集合的底層是二叉樹進行排序的,集合元素唯一性

常用方法:

TreeSet判斷元素唯一性的方式:根據比較方法的返回結果判斷,是0,就是相同元素;不是0,元素不相同

TreeSet對元素進行排序的方式

  • 元素自身具備比較性:元素實現Comparable介面,重寫compareTo方法
  • 容器具備比較性:使用帶參構造建立TreeSet(Collection<? extends E> c) ,實現compare(T o1, T o2)方法

注意:當Comparable比較方式和Comparator比較方式同時存在時,以Comparator的比較方式為主。

   /**
     * 驗證TreeSet集合的唯一、排序
     */

    @Test
    public void test08() {
        TreeSet<String> ts = new TreeSet<>();
        ts.add("5");
        ts.add("2");
        ts.add("3");
        ts.add("4");
        ts.add("1");
        ts.add("5");
        Iterator<String> ite = ts.iterator();
        while (ite.hasNext()) {
            Object next = ite.next();
            System.out.print(next + " ");// 輸出結果:1 2 3 4 5
        }
    }

三、總結(集合框架中常用類比較)

看到array,就要想到角標

看到link,就要想到first,last

看到hash,就要想到hashCode,equals

看到tree,就要想到兩個介面Comparable,Comparator