Java 第十一天(純乾貨)(Collection 、ArrayList 、List集合、迭代器、增強for)(帶你14天瞭解並掌握Java SE)

今日內容

  • 集合的概述和Collection集合
  • List集合
  • 數據結構和ArrayList集合的相關案例

01. 爲什麼會出現集合類

  • 1. 集合的特點
  • 2. 爲什麼要有集合
總結:
    1. 相同點: 集合和數組都是容器, 用來存儲數據的

       不同點:
                數組存儲:可以存儲基本數據類型, 也可以存儲引用數據類型
                        存儲基本數據類型的時候, 存儲的是值              int[] arr = {11,22,33};
                                                                    Person p1 = new Perosn();  Person p2 = new Person();
                        存儲引用數據類型的時候, 存儲的是地址值            Person[] pArr = new Person[2];
                                                                    pArr[0] = p1;   pArr[1] = p2;


                集合存儲: 只能存儲引用數據類型


                長度: 數組的長度是固定的, 集合的長度可變的.

    2. 舉例:
            學生管理系統, 記錄學生的各項信息

                    如果使用數組進行存儲, 數組長度初始爲80個大小, 這時候插班進來的第81個學生就沒有位置存儲了.   

                    問題產生: 使用數組就不合適了

                        解決方案: 使用一個長度可變的容器, [集合]

02. 集合類體系結構圖

  • 再畫一張

03. 創建Collection集合對象並添加元素

  • 爲什麼要先學習Collection?
  • 創建集合對象的時候, <>代表什麼?
總結:
    1. Collection是單列集合的根接口, 內部定義的規則, 所有實現類都會具備一份


    /*
     * 細節1: 如果一個類沒有找到我們使用的方法, 可以去父類中查詢
     * 
     * 問題: 接口到底有沒有繼承Object類
     * 
     *  細節2: 接口沒有繼承Object類, 但是接口底層會有Object類所有方法的引用
     * 
     * 目的: 就是爲了方式多態調用方法的編譯報錯!
     */
    2. <> : 泛型(jdk1.5新特性) -> 用於限制集合中存儲的數據類型

            集合存儲: 只能存儲引用數據類型, 是因爲泛型的特點, <>中只能編寫引用數據類型


代碼:
    public class Demo1_Collection {
        public static void main(String[] args) {
            // 1. 創建集合對象
            // 在jdk1.7版本之後, 右側的尖括號中可以不寫類型, 菱形泛型
            // <> : 泛型 -> 用於限制集合中存儲的數據類型
            Collection<String> c = new ArrayList<>();
            // 2. 向集合中添加元素
            c.add("abc");
            c.add("bbb");
            // 3. 展示集合中的元素
            System.out.println(c.toString());
        }
    }

04. Collection集合的成員方法

  • boolean add(E e):添加元素
  • boolean remove(Object o):從集合中移除元素 ***
  • void clear():清空集合中的元素
  • boolean contains(Object o):判斷集合中是否存在指定的元素 ***
  • boolean isEmpty():判斷集合是否爲空
  • int size():集合的長度,也就是集合中元素的個數

    示例代碼:

    public static void main(String[] args) {
        // 1. 創建集合對象, 容器中存儲的是Person對象
        Collection<Person> c = new ArrayList<>();
        // 2. 向集合中添加Person對象.
        c.add(new Person("張三", 23)); 
        c.add(new Person("李四", 24));
        c.add(new Person("王五", 25));
    
        // 注意: 如果添加的元素是自定義對象的話, 那麼沒有重寫toString, 將打印地址值
        System.out.println(c);
    
        // 3. 調用集合的刪除方法, 刪除張三
        // 注意 : remove方法底層依賴於equals方法.
        c.remove(new Person("張三", 23));
        System.out.println(c);
    
        // 4. 調用集合中判斷是否包含的方法
        // 注意 : contains方法底層依賴於equals方法.
        System.out.println(c.contains(new Person("李四", 24)));
    
        // 5. 調用集合的清空方法
        c.clear();
        // 6. 調用集合判斷是否爲空的方法
        System.out.println(c.isEmpty());
        // 7. 打印集合的長度
        System.out.println(c.size());
    }
    

05. Collection集合的遍歷

  • 使用迭代器遍歷集合的步驟
總結:
    1. 調用集合的iterator方法, 獲取迭代器
            Iterator<String> it = c.iterator();
    2. 使用循環判斷集合中是否還有元素
            while(it.hasNext()){

            }
    3. 使用next方法元素取出
            while(it.hasNext()){
                String s = it.next();
            }


示例代碼:

        public static void main(String[] args) {
            Collection<Person> c = new ArrayList<>();
            c.add(new Person("張三", 23)); 
            c.add(new Person("李四", 24));
            c.add(new Person("王五", 25));

            // 1. 獲取迭代器對象
            Iterator<Person> it = c.iterator();
            // 2. 循環判斷集合中是否還有元素
            while(it.hasNext()){
                // 3. 獲取元素
                Person p = it.next();
                System.out.println(p);
            }
        }

06. 集合(迭代器)使用步驟圖解

  • 看圖說話

07. Collection集合的練習存儲自定義對象並遍歷

  • 需求: 定義一個標準的學生類, 創建三個學生對象存儲到集合容器中, 並遍歷集合.

  • 6分鐘練習

08. List集合的特點

  • List集合有什麼特點?
總結:
    1. 存取有序
    2. 有索引
    3. 可以存儲重複的

09. List集合的特有成員方法

  • void add(int index, E element) :將元素添加到index索引位置上
  • E get(int index) :根據index索引獲取元素
  • E remove(int index) :根據index索引刪除元素
  • E set(int index, E element):將index索引位置的的元素設置爲element

10. List集合的普通for循環遍歷

  • 案例演示
public class Test2_List {
    /*
     * List集合特有的一種遍歷方式
     *      1. get(int index) : 根據傳入的索引, 獲取指定位置的元素
     *      2. size() : 返回集合的長度
     */
    public static void main(String[] args) {
        List<String> list = new ArrayList<>();
        list.add("abc1");
        list.add("abc2");
        list.add("abc3");
        list.add("abc4");

//      String s1 = list.get(0);
//      String s2 = list.get(1);
//      String s3 = list.get(2);
//      String s4 = list.get(3);

        for(int i = 0; i < list.size(); i++){
            System.out.println(list.get(i));
        }

    }
}

11. List集合的練習存儲自定義對象並遍歷

  • 需求: 定義一個標準的學生類, 創建三個學生對象存儲到集合容器中, 並遍歷集合.
    1. 普通for循環

    2. 普通迭代器

    3. ListIterator特有的迭代器 --> 基本使用和普通迭代器一致

        // 1. 獲取列表迭代器
        ListIterator<Student> listIt = list.listIterator();
        // 2. 判斷集合中是否還有元素
        while(listIt.hasNext()){
            // 3. 調用next獲取元素
            System.out.println(listIt.next());
        }

12. 列表迭代器的特有功能(瞭解)

  • 方法摘要:
總結:
    1.boolean hasPrevious()  : 判斷集合是否還有上一個元素
    2.E previous()          : 獲取集合中的上一個元素.

注意: 特有的功能比較雞肋
            倒序遍歷之前, 必須有正序遍歷的鋪墊, 才能取出來元素


    List<Person> list = new ArrayList<>();
    list.add(new Person("張三", 23));
    list.add(new Person("李四", 24));
    list.add(new Person("王五", 25));

    // 1. 獲取列表迭代器
    ListIterator<Person> it = list.listIterator();

    // 2. 循環判斷是否還有元素
    while(it.hasNext()){
        // 3. 使用next方法獲取元素
        System.out.println(it.next());
    }

    System.out.println("----------------------");


    while(it.hasPrevious()){
        System.out.println(it.previous());
    }
  • 5分鐘時間練習

13. 併發修改異常產生的原因及解決方案(重點)

  • 什麼情況下會產生併發修改異常?
  • 如何解決?
總結:
    1. 當使用迭代器在遍歷集合的過程中, 使用集合的添加或刪除方法操作元素
                就會產生併發修改異常

    2. 不讓使用集合的添加或刪除, 就使用迭代器自身的添加或刪除

            刪除: 普通迭代器中存在

            添加: 列表迭代器

擴展:
    如果用集合的remove方法刪除的是倒數第二個元素的時候, 則不會報出併發修改異常(瞭解)

        原因: 略過了編譯器的檢查.      -> 少調用了一次checkxxxxx方法

14. 增強for(jdk1.5的新特性)的概述和使用

  • 增強for循環的格式是?
  • 增強for循環底層依賴於什麼技術實現?
總結:
    1. 

        for(數據類型 變量名 : 要遍歷的數組或集合){

        }

    2.

        增強for循環底層是迭代器實現的

            只要是能用迭代器遍歷的容器, 都可以使用增強for循環改進.

            注意1: 增強for循環不能使用集合的刪除方法, 會產生併發修改異常
            注意2: 增強for循環中, 不能刪除元素

15. 增強for的練習List集合存儲自定義對象並遍歷

  • 案例演示
public static void main(String[] args) {
    List<Person> list = new ArrayList<>();
    list.add(new Person("張三", 23));
    list.add(new Person("李四", 24));
    list.add(new Person("王五", 25));

    for(Person p : list){
        System.out.println(p);
    }
}

16. 常見數據結構之棧和隊列

  • 棧內存結構什麼特點?
  • 隊列內存結構什麼特點?
總結:
    1: 桟內存結構,類似於手槍彈夾
            特點: 先進後出
    2: 隊列內存結構, 類似於一條管道
            特點: 先進先出

17. 常見數據結構之數組和鏈表

  • 數組
    優點:查詢快, 修改快

            原因: 因爲數組有索引, 有索引的話, 就可以快速的定位到要操作的元素, 並快速的進行修改.

    缺點:增刪慢

            原因: 因爲每一次的添加或刪除都需要大批量的操作數據中的元素

                    刪除: 將數組中的元素刪除之後, 後面的元素會整體的向前移動一位
                            假如數組長度爲100, 我們將第一個元素進行刪除, 後續的99個元素都要進行移動

                    增加: 以ArrayList爲舉例, 底層就是數組結構的, 假設底層數組長度爲10個大小, 我們在添加第11個元素的時候
                            底層就會根據原數組, 自動擴容一個1.5倍大小的新數組, 再將數組內容拷貝一份到新數組中去, 隨後再把第11個元素進行添加.
  • 鏈表
    優點: 增刪快

                只需要將兩個元素的引用切斷, 然後重新規劃引用即可, 不會影響到過多的元素.

                刪除也是如此.

    缺點: 查詢慢, 修改慢

                每一次查找元素, 都會在鏈表結構當中, 逐個的做元素檢索.


                問題: 查詢元素的時候從頭開始查, 還是從尾開始查?

                        底層源碼會進行一個判斷, 如果離頭近, 就從前往後找, 如果離尾近, 從後往前找.

                            問題: 如何進行的判斷?

                                    會根據索引進行折半查找

                                    問題: LinkedList有索引嗎?

                                            因爲是List派系下的子類,所以存在索引, 但是查找的時候就是不用!

18. List集合子類特點及ArrayList集合存儲字符串並遍歷

  • ArrayList集合的特點, 完成什麼樣的功能較爲合適?
總結:
    1.

        ArrayList<String> list = new ArrayList<>();

        list.add("abc");
        list.add("111");
        list.add("222");
        list.add("333");

        for (int i = 0; i < list.size(); i++) {
            System.out.println(list.get(i));
        }

        System.out.println("-------------");


        Iterator<String> it = list.iterator();
        while(it.hasNext()){
            System.out.println(it.next());
        }

        System.out.println("--------------------");

        for(String s : list){
            System.out.println(s);
        }

19. ArrayList集合的練習存儲自定義對象並遍歷

  • 回顧3種集合的迭代方式
    三種遍歷是否能刪除元素.
        1. 迭代器:  可以刪除, 但是在調用remove方法之前必須調用next方法
                            問題: next方法會將指針向後移動一位, 爲什麼不需要--
                            答案: 底層自動幫我們實現了--的操作.
        2. 普通for : 可以刪除, 但是索引需要--
        3. 增強for : 不能刪, 因爲會產生併發修改異常
  • 案例演示LinkedList集合的使用.
    public static void main(String[] args) {
        // 底層是鏈表結構
        LinkedList<String> list = new LinkedList<>();

        // 調用從Collection中繼承下來的add方法添加元素
        list.add("1");
        list.add("2");
        list.add("3");

        // LinkedList特有的方法: 在頭部添加元素
        list.addFirst("4");
        list.addFirst("5");

        // LinkedList特有的方法: 在尾部添加元素
        list.addLast("6");

        // LinkedList特有的方法: 刪除第一個元素
        list.removeFirst();

        // LinkedList特有的方法: 刪除最後一個元素
        list.removeLast();

        System.out.println(list);
    }
  • 問題: LinkedList集合底層是鏈表結構, 那麼查詢元素的時候從前開始找, 還是從後開始找?
    總結:
            1. 會查看要查找的元素, 離頭近還是離尾近, 如果離頭近, 就從頭開始找, 反之, 就從尾開始找.
            2. LinkedList雖然是鏈表結構, 但是底層也有索引 !
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章