1. 程式人生 > 實用技巧 >Java自學第6期——Collection、Map、迭代器、泛型、可變引數、集合工具類、集合資料結構、Debug

Java自學第6期——Collection、Map、迭代器、泛型、可變引數、集合工具類、集合資料結構、Debug

集合:集合是java中提供的一種容器,可以用來儲存多個數據。

集合和陣列既然都是容器,它們有啥區別呢?

  • 陣列的長度是固定的。集合的長度是可變的。
  • 陣列中儲存的是同一型別的元素,可以儲存基本資料型別值。集合儲存的都是物件。而且物件的型別可以不一致。
  • 在開發中一般當物件多的時候,使用集合進行儲存。

集合按照其儲存結構可以分為兩大類,分別是
單列集合java.util.Collection和雙列集合java.util.Map
綜述:

根接 口 Collection Map
子介面 List、Set 未學
實現類 Vector、LinkedList、ArrayList,HashSet、TreeSet HashMap
再子類 LinkedHashSet LinkedHashMap

一、Collection介面

  • Collection:單列集合類的根介面,用於儲存一系列符合某種規則的元素,它有兩個重要的子介面,
  • 分別是java.util.Listjava.util.Set
  • 其中,List的特點是元素有序、元素可重複。
  • Set的特點是元素無序,而且不可重複。
  • List介面的主要實現類有java.util.ArrayListjava.util.LinkedList
  • Set介面的主要實現類有java.util.HashSetjava.util.TreeSet
  • Collection沒有索引,不能直接遍歷,先轉換成陣列

Collection是所有單列集合的父介面,因此在Collection中定義了單列集合(List和Set)通用的一些方法,

  • 這些方法可用於操作所有的單列集合。方法如下:

  • public boolean add(E e): 把給定的物件新增到當前集合中 。可以不用接收

  • public void clear() :清空集合中所有的元素。

  • public boolean remove(E e): 把給定的物件在當前集合中刪除。

  • public boolean contains(E e): 判斷當前集合中是否包含給定的物件。

  • public boolean isEmpty(): 判斷當前集合是否為空。

  • public int size(): 返回集合中元素的個數。

  • public Object[] toArray(): 把集合中的元素,儲存到陣列中。

public static void main(String[] args) {
        //多型,介面指向實現類
        //此處ArrayList改成HashSet等其他集合也可以,方法一樣
        Collection<String> collection1 = new ArrayList<>();
//        Collection<String> collection1 = new HashSet<>();
        //列印空,不是地址,說明重寫了toString方法
        System.out.println(collection1);
        collection1.add("kiana");
        //列印[kiana]
        System.out.println(collection1);
        collection1.add("bronya");
        collection1.add("Fuka");
        //[kiana, bronya, Fuka]
        System.out.println(collection1);
        collection1.remove("bronya");
        //[kiana, Fuka]
        System.out.println(collection1);
        //判斷有無元素Mei
        boolean criticalResult = collection1.contains("Mei");
        //false
        System.out.println(criticalResult);
        //判斷集合是否為空
        boolean Result2 = collection1.isEmpty();
        //false
        System.out.println(Result2);
        int sizeResult = collection1.size();
        //2
        System.out.println(sizeResult);
        //把集合變成陣列
        Object[] array = collection1.toArray();
        //遍歷陣列,kiana Fuka
        for (int i = 0; i <array.length ; i++) {
            System.out.println(array[i]);
        }
        //刪除集合元素,集合本身還在
        collection1.clear();
        //輸出[]
        System.out.println(collection1);
        }

二、迭代器

Iterator迭代器,是Collection集合通用的取出元素的方式,先判斷集合有沒有元素,有就取出一個元素,再繼續判斷有沒有元素……直到把集合中所有元素全部取出。這種取出方式稱作迭代。

boolean hasNext():(判斷)如果仍有元素可以迭代,則返回 true。
E next():(取出)返回迭代的下一個元素。
void remove():從迭代器指向的 collection 中移除迭代器返回的最後一個元素(可選操作)。

Iterator是介面 不能直接使用,需要介面的實現類。注意,Iterator介面也是有泛型的,與集合相同。Collection接口裡有個方法:
iterator() ,返回的就是Iterator的實現類物件。
Iterator iterator(): 返回在此 collection 的元素上進行迭代的迭代器。

public static void main(String[] args) {
        Collection<String> collection1 = new ArrayList<>();
        collection1.add("板鴨");
        collection1.add("芽衣");
        //[板鴨, 芽衣]
        System.out.println(collection1);
        //第一步,獲取這個集合的迭代器。介面指向實現類物件
        Iterator<String> iterator = collection1.iterator();
        //第二步,判斷有沒有元素
        System.out.println(iterator.hasNext());
        //第三步,取出元素
        String next = iterator.next();
        //板鴨
        System.out.println(next);
        //true
        System.out.println(iterator.hasNext());
        //芽衣
        System.out.println(iterator.next());
        //已經沒有元素了,再取會丟擲NoSuchElementException沒有元素異常
//        System.out.println(iterator.next());

        //優化
        Collection<String> collection2 = new ArrayList<>();
        collection2.add("板鴨");
        collection2.add("芽衣");
        Iterator<String> iterator1 = collection2.iterator();
        //板鴨芽衣
        while(iterator1.hasNext()){
            System.out.print(iterator1.next());
            
        }
    }

三、泛型

  • 泛型:一種未知的資料型別,定義集合時若暫未確定集合內元素型別,可使用泛型。
  • 泛型也可以看作是一個變數,用來接收資料型別。
  • E e:Element 元素
  • T t:Type 型別
  • 建立集合物件的時候,就會確認泛型的資料型別
    *不使用泛型時,預設Object型別,可以儲存任意型別的資料。壞處:不安全,會引發異常。
  • 好處:避免了型別轉換的麻煩;把執行期異常,提升到了編譯期。
public static void main(String[] args) {
        method1();
        method2();
    }
    /*
    建立集合物件,不使用泛型時,預設Object型別,可以儲存任意型別的資料。
    壞處:不安全,會引發異常。
     */
    private static void method1(){
        ArrayList array1 = new ArrayList();//建立集合
        array1.add("女武神");//儲存字串
        array1.add(12);//儲存整數
        //使用迭代器遍歷
        Iterator iterator1 = array1.iterator();
        while(iterator1.hasNext()){
            Object obj1 = iterator1.next();
            System.out.println(obj1);//輸出:女武神 12

            //假如要使用String類裡的lenghth()輸出字串長度,
            // 需要把Object型別的obj1向下轉型為String型別
            String string1 = (String)obj1;
            System.out.println(string1.length());//3
            //上面產生了ClassCastException型別轉換異常,這就是不使用泛型的缺點
        }
    }
    private static void method2(){
        ArrayList<String> list = new ArrayList<>();
        list.add("Valkyrie");

        Iterator<String> iterator2 = list.iterator();
        while(iterator2.hasNext()){
            System.out.println(iterator2.next());
        }
    }
  • 定義一個含有泛型的資料型別,模擬ArrayList集合。
  • 泛型可以接收任意的資料型別,可以使用Integer,String、Object……
  • 建立物件的時候確定泛型的資料型別。
  • 不寫泛型預設是Object型別
//新增泛型E:
public class Demo05_class<E> {
    private E name;

    public E getName() {
        return name;
    }

    public void setName(E name) {
        this.name = name;
    }
}
  • 測試類
    物件類寫成泛型,不把它寫死,要什麼型別就在建立物件的時候定義
 */
public class Demo05_class1 {

    public static void main(String[] args) {
        //不寫泛型預設是Object型別
        Demo05_class obj = new Demo05_class();
        obj.setName("字串");

        //建立Demo05_class物件,使用Integer泛型
        Demo05_class<Integer> obj2 = new Demo05_class<>();
        obj2.setName(123);
        System.out.println(obj2.getName());

        //使用含有泛型的方法
        Demo05_method obj3 = new Demo05_method();
        //傳遞什麼型別,泛型就是什麼型別
        obj3.method1("666");//String
        obj3.method1(666);//Integer
        //靜態方法通過類名點方法名直接使用。
        Demo05_method.method2("666");

        //建立介面實現類物件方法1
        Demo05_InterfaceImpl obj4 = new Demo05_InterfaceImpl();
        obj4.method4("888");
        //建立介面實現類物件方法2,在建立物件時確認泛型
        Demo05_InterfaceImpl2<String> obj5 = new Demo05_InterfaceImpl2();
        obj5.method4("字串");

    }
  • 定義介面的實現類,指定介面的泛型
public interface Iterator<E>{
    E next();
}
public class Demo05_InterfaceImpl implements Demo05_Interface<String> {
    @Override
    public void method4(String i){
        System.out.println(i);
    }
}
  • 介面和實現類後都寫上泛型, 重寫時泛型作為引數進入方法
public class Demo05_InterfaceImpl2<I> implements Demo05_Interface<I> {
    @Override
    public void method4(I i){
        System.out.println("重寫2");
    }

}
  • 定義含有泛型的方法:
    泛型定義在方法的修飾符和返回值之間,引數列表裡可以通過泛型使用
    在呼叫方法的時候確認泛型的使用型別
public class Demo05_method {

    public <E> void method1(E one) {
        System.out.println(one);
    }
    //定義一個含有泛型的靜態方法
    public static <S> void method2(S s){
        System.out.println("含有泛型的靜態方法");
    }
}
  • 泛型萬用字元<?>在引數傳遞的時候使用
public static void main(String[] args) {
        ArrayList<String> list1 = new ArrayList<>();
        list1.add("字串");
        ArrayList<Integer> list2 = new ArrayList<>();
        list2.add(666);
        //該方法能同時呼叫不同型別的集合
        method1(list1);//字串
        method1(list2);//666
    }
    //泛型萬用字元在引數傳遞的時候使用
    public static void method1(ArrayList<?> list){
        Iterator<?> iterator1 = list.iterator();
        while(iterator1.hasNext()){
            System.out.println(iterator1.next());
        }
    }

鬥地主案例實現

public static void main(String[] args) {
        //定義儲存54張牌的ArrayList集合
        ArrayList<String> array1 = new ArrayList<>();
        //定義兩個陣列,一個儲存花色,一個儲存序號
        String[] colors = {"黑桃","紅桃","方塊","梅花"};
        String[] nubers = {"3","4","5","6","7","8","9","10","J","Q","K","A","2"};
        //集合裡儲存大王小王
        array1.add("大王");
        array1.add("小王");
        //迴圈巢狀兩個陣列,組裝52張牌
        for (String numbers:nubers){
            for (String colours : colors) {
                //System.out.println(colours+numbers);
                //把組裝好的牌儲存到集合中
                array1.add(colours+numbers);
            }
        }
//        System.out.println(array1);
        //洗牌,通過Collections裡的shuffle方法
        Collections.shuffle(array1);
//        System.out.println(array1);
        //定義四個集合,儲存玩家的牌
        ArrayList<String> play01 = new ArrayList<>();
        ArrayList<String> play02 = new ArrayList<>();
        ArrayList<String> play03 = new ArrayList<>();
        ArrayList<String> dipai = new ArrayList<>();
        //發牌
        System.out.println(array1.size());
        for (int i = 0; i < array1.size() ; i++) {
            //獲取每一張牌
            String str1 = array1.get(i);
            if ( i>=51){
                //底牌
                dipai.add(str1);
            }else if (i%3==0){
                //玩家1發牌
                play01.add(str1);
            }else if (i%3==1){
                //玩家2發牌
                play02.add(str1);
            }else if (i%3==2){
                //玩家3發牌
                play03.add(str1);
            }
        }
        //看牌
        System.out.println("1號:" + play01);
        System.out.println("2號:" + play02);
        System.out.println("3號:" + play03);
        System.out.println("底牌:"+ dipai);
    }

四、List介面

Collection下一個List一個Set。
List集合下的實現類中,ArrayList查詢快,增刪慢;LinkedList是List藉口的連結串列實現,查詢慢,增刪快。

import java.util.List;

  • List:有序集合(存取順序相同),有索引,允許儲存重複元素。底層是陣列。此實現是多執行緒,非同步。
  • 方法:
    boolean add(E e)
    向列表的尾部新增指定的元素(可選操作)。
    void add(int index, E element)
    在列表的指定位置插入指定元素(可選操作)。
    E get(int index)
    返回列表中指定位置的元素。
    ListIterator listIterator()
    返回此列表元素的列表迭代器(按適當順序)。
    ListIterator istIterator(int index)
    返回列表中元素的列表迭代器(按適當順序),從列表的指定位置開始。
    E remove(int index)
    移除列表中指定位置的元素(可選操作)。
    boolean remove(Object o)
    從此列表中移除第一次出現的指定元素(如果存在)(可選操作)。
public static void main(String[] args) {
        //多型
        List<String> list1 = new ArrayList<>();
        list1.add("光");
        list1.add("翼");
        list1.add("展");
        list1.add("開");
        list1.add(0,"kiana");
        System.out.println(list1.get(0));//kiana
        ListIterator<String> listIterator1 = list1.listIterator();
        ListIterator<String> listIterator2 = list1.listIterator(1);
        while(listIterator1.hasNext()){
            System.out.println(listIterator1.next());//kiana 光 翼 展 開
        }
        while(listIterator2.hasNext()){
            System.out.println(listIterator2.next());//光翼展開
        }
        list1.remove(0);
        System.out.println(list1);//[光, 翼, 展, 開]
        list1.remove("光");
        System.out.println(list1);//[翼, 展, 開]

    }

實現類LinkedList

  • LinkedList集合查詢慢,增刪快,含有大量用於修改首尾的方法。
    如果使用LinkedList特有的方法,則不能使用多型
  • 方法:
    void addFirst(E e):
    將指定元素插入此列表的開頭。
    void addLast(E e):
    將指定元素新增到此列表的結尾。
    void clear()
    從此列表中移除所有元素。
    boolean contains(Object o):
    如果此列表包含指定元素,則返回 true。
    E get(int index):
    返回此列表中指定位置處的元素。
    E getFirst():
    返回此列表的第一個元素。
    E getLast()
    返回此列表的最後一個元素。
    E removeFirst()
    移除並返回此列表的第一個元素。
    E removeLast()
    移除並返回此列表的最後一個元素。
public static void main(String[] args) {
        LinkedList<String> list1 = new LinkedList<>();
        list1.add("kiana");
        list1.addFirst("love");
        list1.addLast("is me");
        System.out.println(list1);//[love, kiana, is me]
        System.out.println(list1.get(1));//kiana
        if (list1.contains("love")){
            System.out.println("含有lova");
        }
        list1.removeFirst();
        System.out.println(list1);//[kiana, is me]
    }
  • Vector集合,實現可增長的物件陣列,底層是陣列,已經被ArrayList取代,單執行緒

五、Set介面

Collection的另一個孩子,

1.不能儲存重複元素。
2.沒有索引,不能使用普通的for迴圈遍歷。
3.底層是雜湊表結構,查詢速度很快,存取元素順序可能不一致。
4.HashSet集合類實現Set介面;

  • 方法:
    boolean add(E e):
    如果 set 中尚未存在指定的元素,則新增此元素(可選操作)。
    boolean addAll(Collection<? extends E> c):
    如果 set 中沒有指定 collection 中的所有元素,則將其新增到此 set 中(可選操作)。
    void clear():
    移除此 set 中的所有元素(可選操作)。
    boolean contains(Object o):
    如果 set 包含指定的元素,則返回 true。
    boolean containsAll(Collection<?> c):
    如果此 set 包含指定 collection 的所有元素,則返回 true。
    boolean equals(Object o):
    比較指定物件與此 set 的相等性。
    int hashCode():
    返回 set 的雜湊碼值。
    boolean isEmpty():
    如果 set 不包含元素,則返回 true。
    Iterator iterator()
    返回在此 set 中的元素上進行迭代的迭代器。
    boolean remove(Object o)
    如果 set 中存在指定的元素,則將其移除(可選操作)。
    boolean removeAll(Collection<?> c):
    移除 set 中那些包含在指定 collection 中的元素(可選操作)。
    boolean retainAll(Collection<?> c):
    僅保留 set 中那些包含在指定 collection 中的元素(可選操作)。
    int size():
    返回 set 中的元素數(其容量)。
    Object[] toArray():
    返回一個包含 set 中所有元素的陣列。
    T[] toArray(T[] a):
    返回一個包含此 set 中所有元素的陣列;返回陣列的執行時型別是指定陣列的型別。
public static void main(String[] args) {
        Set<String> setList1 = new HashSet<>();
        setList1.add("Mei");
        setList1.add("逐火之蛾");
        setList1.add("Mei");//重複元素儲存失敗
        System.out.println(setList1.contains("Mei"));
        Iterator<String> iterator1 = setList1.iterator();
        while (iterator1.hasNext()){
            System.out.println(iterator1.next());
        }
        System.out.println(setList1.size());

HashSet實現類

  • 雜湊值是一個十進位制的整數,由系統隨機給出。
    Object類的hashCode方法返回物件的雜湊碼值:
    int hashCode()
    jdk1.8之後,雜湊表=陣列+紅黑樹(加快查詢速度)
    儲存資料到集合中,首先計算元素的雜湊值
  • 沒有重寫時,HashSet比較的是兩個物件的地址值,
    儲存自定義型別的元素時必須重寫hashCode和equals方法同時比較元素和雜湊值更穩妥。
    按Alt+Insert重寫方法
 @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;
        Demo11_Hash that = (Demo11_Hash) o;
        return Objects.equals(name, that.name) &&
                Objects.equals(age, that.age);
    }
@Override
    public int hashCode() {
        return super.hashCode();
    }

LinkedHashSet(繼承HashSet)

  • 具有可預知迭代順序的Set介面的雜湊表和連結串列實現
    LinkedHashSet集合extends了HashSet集合,
    LinkedHashSet集合底層是雜湊表(連結串列+陣列/紅黑樹)+連結串列,多的連結串列用來記錄元素儲存順序,保證元素有序
public static void main(String[] args) {
        HashSet<String> set1 = new HashSet<>();
        set1.add("a");
        set1.add("a");
        set1.add("c");
        set1.add("b");
        System.out.println(set1);//[a, b, c],無重複,無順序

        LinkedHashSet<String> linkedset2 = new LinkedHashSet<>();
        linkedset2.add("a");
        linkedset2.add("a");
        linkedset2.add("c");
        linkedset2.add("b");
        System.out.println(linkedset2);//[a, c, b],有順序,無重複
    }

六、可變引數

  • 可變引數:當方法的引數列表資料型別已經確定,但引數的資料型別不確定,就可以使用可變引數
    使用格式:定義方法時使用
    修飾符 返回值型別 方法名(資料型別...變數名){}
    原理:可變引數底層是陣列,根據傳遞引數個數不同,會建立不同長度的陣列,來儲存這些引數。
    傳遞的引數個數可以是0個(不傳遞),1,2,3...很多個。
    可變引數的終極寫法:
    (Object...obj)
  • 注意:
    一個方法的引數列表,只能有一個可變引數。
    如果方法的引數有多個,那麼可變引數必須寫在引數列表的末尾。
public static void main(String[] args) {
        Sum1();
        System.out.println(Sum2(222,111,223,3));//559
        Sum3(33,"w",3.14);
    }
    //定義一個方法,計算兩個int整數的和
    public static void Sum1(){
        System.out.println("請輸入倆數字");
        Scanner num1 = new Scanner(System.in);
        Scanner num2 = new Scanner(System.in);
        int sum = num1.nextInt()+num2.nextInt();
        System.out.println(sum);
    }
    //計算未定數目的引數的和
    public static int Sum2(int...num3){
        int Sum= 0;
        for (int i : num3) {
            Sum += i;
        }
        return Sum;
    }
    public static void Sum3(Object...obj){
        for (Object o : obj) {
            System.out.println(o);
        }
    }

七、Collections工具類

Collections工具類:java.utils.Collections

  • 方法:
    public static boolean addAll(Collection c,T...elements)
    往集合中新增多個元素
    public static void shuffle(List list)
    打亂集合順序
    public static void sort(List list)
    將集合中的元素按照預設順序排序
    public static void sort(List list,Comparator <? super T>)
    將集合中的元素按照指定規則排序
  • 注:被排序的集合裡的元素,必須實現Comparable介面,重寫介面中的compareTo定義排序的規則
public static void main(String[] args) {
        ArrayList<String> list1 = new ArrayList<>();
        //addAll
        Collections.addAll(list1,"k","i","a","n","a");
        System.out.println("addAll:"+list1);
        //shuffle
        Collections.shuffle(list1);
        System.out.println("打亂後:"+list1);
        //sort預設(數字預設大小升序,字串預設自然升序abcdefg...)
        Collections.sort(list1);
        System.out.println("預設排序後:"+list1);//[a, a, i, k, n]
        //sort指定,重寫排序規則
        ArrayList<Integer> list2 = new ArrayList<>();
        list2.add(1);
        list2.add(3);
        list2.add(2);
        Collections.sort(list2, new Comparator<Integer>() {
            @Override
            public int compare(Integer o1, Integer o2) {
                //o1-o2代表升序,o2-o1代表降序
                return o1-o2;
            }
        });
        System.out.println(list2);//1,2,3
        //自定義型別Demo00_Person的排列
        ArrayList<Demo00_Person> list3 = new ArrayList<>();
        list3.add(new Demo00_Person("琪亞娜",17));
        list3.add(new Demo00_Person("芽衣",18));
        list3.add(new Demo00_Person("板鴨",15));
        list3.add(new Demo00_Person("艦長",20));
        System.out.println("自定義型別排列前:"+list3);
        Collections.sort(list3, new Comparator<Demo00_Person>() {
            @Override
            public int compare(Demo00_Person o1, Demo00_Person o2) {
                //先按年齡排列
                int result = o1.getAge() - o2.getAge();
                //如果年齡相同,按照名字排列
                if(result == 0){
                    result = o1.getName().charAt(0)-o2.getName().charAt(0);
                }
                return result;
            }
        });
        System.out.println("自定義型別排列後:"+list3);

八、集合資料結構

和集合相關的資料結構:棧、佇列,陣列,連結串列,紅黑樹。

  • 棧:先進後出
    元素儲存到集合中時,先儲存的元素在棧的底部,後進入的元素在棧的頂部,
    取出元素時,先取出棧頂部的元素,棧底部的元素後取出。棧的出口和入口相同。
    例如:入棧順序123,出棧的順序即為321。

  • 佇列:先進先出
    入口和出口不同,先入者接近出口,後入者離出口較遠。

  • 陣列:查詢快,增刪慢。
    查詢快:陣列的地址是連續的,通過首地址找到陣列,再通過索引找到想要的陣列元素。
    增刪慢:陣列的長度是固定的,增刪陣列需要建立一個新的陣列,並將源陣列的資料複製到新陣列中。
    源陣列在記憶體中被銷燬(垃圾回收)。

  • 連結串列(linked list):由一系列節點node(連結串列中的元素)組成,節點在執行時動態生成。
    每個節點包含一個儲存資料元素的資料域,和兩個分別儲存自己和下一個節點地址的指標域。
    連結串列結構通常有單向連結串列和雙向連結串列。多個節點間通過地址相連。
  • 單向連結串列:連結串列中只有一條鏈子,不能保證元素的順序。儲存、取出的資料可能不一致。
  • 雙向連結串列:有兩條鏈子,其中一條專門記錄元素的順序,所是一個有序的集合.
    查詢慢:想查詢某個元素,需要通過連線的節點,一次向後查詢指定元素。地址不連續,每次查詢需要從頭開始。
    增刪快:增刪元素對連結串列整體結構沒有影響,所以快。

  • 紅黑樹:
    二叉樹:分支不能超過兩格的樹
    排序樹/查詢樹:在二叉樹的基礎上,元素是有大小的,左子樹小,右子樹大
    紅黑樹:節點紅色或黑色,根節點黑色,葉子節點黑色,每個紅色的節點的子節點都是黑色,任何節點到其
    每一個葉子節點的所有路徑上黑色節點的數量是相同的。

九、Map集合介面

java裡集合除了Collections(List/Set)外就是Map集合,用來存放對映關係的物件。

  • Collection中的集合,元素是孤立存在的(理解為單身),向集合中儲存元素採用一個個元素的方式儲存。
  • Map 中的集合,元素是成對存在的(理解為夫妻)。每個元素由鍵與值兩部分組成,通過鍵可以找對所對應的值。
  • Collection 中的集合稱為單列集合, Map 中的集合稱為雙列集合。
    需要注意的是, Map 中的集合不能包含重複的鍵,值可以重複;每個鍵只能對應一個值。
  • java.util.Map<k,v> :key鍵,value值,通過key可以找到對應的value,
    value可以重複,一個key對應一個value,key不可以重複。
    key和map資料型別可以相同可以不同,
    靠key維護他們之間的關係。

HashMap:

Map的兩個常用子類:HashMap和LinkedHashMap

  • HashMap:儲存資料採用的雜湊表結構,元素的存取順序不能保證一致。
    由於要保證鍵的唯一、不重複,需 要重寫鍵的hashCode()方法、equals()方法。
  • LinkedHashMap:HashMap下有個子類LinkedHashMap,儲存資料採用的雜湊表結構+連結串列結構。
    通過連結串列結構可以保證元素的存取順序一致;通過雜湊表結構可以保證的鍵的唯一、不重複,
    需要重寫鍵的 hashCode()方法、equals()方法。

tips:Map介面中的集合都有兩個泛型變數,在使用時,要為兩個泛型變數賦予資料型別。
兩個泛型變數的數 據型別可以相同,也可以不同。
tips:Map集合不能直接使用迭代器或者foreach進行遍歷。但是轉成Set之後就可以使用了。

Map介面中定義了很多方法,常用的如下:
public V put(K key, V value) : 把指定的鍵與指定的值新增到Map集合中。
public V remove(Object key) : 把指定的鍵 所對應的鍵值對元素 在Map集合中刪除,返回被刪除元素的值。
public V get(Object key) 根據指定的鍵,在Map集合中獲取對應的值。
public Set keySet() : 獲取Map集合中所有的鍵,儲存到Set集合中。
public Set<Map.Entry<K,V>> entrySet() : 獲取到Map集合中所有的鍵值對物件的集合(Set集合)。

public static void main(String[] args) {
        HashMap<Integer,String> list1 = new HashMap<>();
        list1.put(0,"kiana");
        list1.put(1,"love");
        list1.put(2,"me");
        //kiana
        System.out.println(list1.get(0));
        boolean b = list1.containsKey(5);
        //false
        System.out.println(b);
        //遍歷Map集合,先取出key到set集合,再用Iterator或者增強for
        Set<Integer> setlist1 = list1.keySet();
        Iterator<Integer> iterator = setlist1.iterator();
        while (iterator.hasNext()){
            Integer key = iterator.next();
            String value = list1.get(key);
            System.out.println(key+" 對應 "+value);

        }
        for (Integer key1 : setlist1){
            //此處setList1可以直接寫List1.keySet簡化一步
            System.out.println(list1.get(key1));
        }

Entry:

Map 中存放的是兩種物件,一種稱為key(鍵),一種稱為value(值),
它們在在 Map 中是一一對應關係,這一對物件又稱做 Map 中的一個 Entry(項)
Entry 將鍵值對的對應關係封裝成了物件。
即鍵值對物件,這樣我們在
遍歷 Map 集合時,就可以從每一個鍵值對( Entry )物件中獲取對應的鍵與對應的值。
既然Entry表示了一對鍵和值,那麼也同樣提供了

  • 獲取對應鍵和對應值的方法:
    public K getKey() :獲取Entry物件中的鍵。
    public V getValue() :獲取Entry物件中的值。
    在Map集合中也提供了
  • 獲取所有Entry物件的方法:
    public Set<Map.Entry<K,V>> entrySet() : 獲取到Map集合中所有的鍵值對物件的集合(Set集合)。
public static void main(String[] args) {
        HashMap<Integer,String> list2 = new HashMap<>();
        //新增三個entry物件
        list2.put(1,"1");
        list2.put(2,"2");
        list2.put(3,"3");
        //獲取entry物件到set集合中
        Set<Map.Entry<Integer, String>> obj1 = list2.entrySet();
        //增強for遍歷set集合,集合裡通過getKey、getValue方法活動物件的鍵值
        for (Map.Entry<Integer, String> integerStringEntry : obj1) {
            Integer key = integerStringEntry.getKey();
            String value = integerStringEntry.getValue();
            System.out.println(key+value);//11,22,33
        }
  • Map集合儲存自定義型別的方法:
    當給HashMap中存放自定義物件時,
    如果自定義物件作為key存在,
    這時要保證物件唯一,必須複寫物件的 hashCode和equals方法.
    如果要保證map中存放的key和取出的順序一致,可以使用 java.util.LinkedHashMap 集合來存放。
public static void main(String[] args) {
        //key寫為自定義型別
        HashMap<Dem00_Person,String> map1 = new HashMap<>();
        //建立自定義物件為引數:
        map1.put(new Dem00_Person("Kiana",16),"大老婆");
        map1.put(new Dem00_Person("Mei",17),"二老婆");
        map1.put(new Dem00_Person("Bronya",14),"三老婆");
        map1.put(new Dem00_Person("Teresa",12),"小老婆");
        //取出元素,鍵找值方式,注意Set型別寫法
        Set<Map.Entry<Dem00_Person,String>> obj2 = map1.entrySet();

集合工廠方法 of():

  • JDK9對集合新增元素的優化:
    通常,我們在程式碼中建立一個集合(例如,List 或 Set ),並直接用一些元素填充它。
    例項化集合,幾個 add方法 呼叫,程式碼顯得重複。
    Java 9,添加了幾種集合工廠方法,更方便建立少量元素的集合、map例項。
    新的List、Set、Map的靜態工廠方法of可以更方便地建立集合的不可變例項。
  • 使用前提:
    1.集合中元素的數確定且不再改變
    2.只適用於List、Set、Map介面,不適用於它們的實現類;
    3.Set和Map存的元素不能有重複,List可以
public static void main(String[] args) {
        List<String> list1 = List.of("k","i","a","n","a","a");
//        list1.add("aa");
//        UnsupportedOperationException不支援操作異常,of返回的集合不可再改變
//        Set<String> set1 = Set.of("a", "a");
//        Set集合儲存重複元素,丟擲IllegalArgumentException非法引數異常
    }

十、Debug

IDEA中:
左邊設定斷點,右鍵選擇Debug執行程式,程式停止在了斷點行不再執行
Debug後,下方按鈕從左到右:

  • Console:切換到控制檯
  • Step Over(F8):程式碼向下執行一行
  • Step Into(F7):進入要呼叫的方法
  • Step Out(shift + F8):跳出方法
    左邊:
  • Resume Program(F9):調到下一個斷點
  • Stop(Ctrl+F2):停止除錯的程式,退出Debug模式