Java自學(xué)第6期——Collection使套、Map、迭代器鞠柄、泛型侦高、可變參數(shù)、集合工具類厌杜、集合數(shù)據(jù)結(jié)構(gòu)奉呛、Debug2019-12-09

集合:集合是java中提供的一種容器,可以用來存儲多個數(shù)據(jù)夯尽。

集合和數(shù)組既然都是容器瞧壮,它們有啥區(qū)別呢?

  • 數(shù)組的長度是固定的匙握。集合的長度是可變的咆槽。
  • 數(shù)組中存儲的是同一類型的元素,可以存儲基本數(shù)據(jù)類型值圈纺。集合存儲的都是對象秦忿。而且對象的類型可以不一致。
  • 在開發(fā)中一般當(dāng)對象多的時候蛾娶,使用集合進(jìn)行存儲灯谣。

集合按照其存儲結(jié)構(gòu)可以分為兩大類,分別是
單列集合java.util.Collection和雙列集合java.util.Map蛔琅,
綜述:

根接 口 Collection Map
子接口 List酬屉、Set 未學(xué)
實(shí)現(xiàn)類 Vector、LinkedList揍愁、ArrayList呐萨,HashSet、TreeSet HashMap
再子類 LinkedHashSet LinkedHashMap

一莽囤、Collection接口

  • Collection:單列集合類的根接口谬擦,用于存儲一系列符合某種規(guī)則的元素,它有兩個重要的子接口朽缎,
  • 分別是java.util.Listjava.util.Set惨远。
  • 其中,List的特點(diǎn)是元素有序话肖、元素可重復(fù)北秽。
  • Set的特點(diǎn)是元素?zé)o序,而且不可重復(fù)最筒。
  • List接口的主要實(shí)現(xiàn)類有java.util.ArrayListjava.util.LinkedList贺氓,
  • Set接口的主要實(shí)現(xiàn)類有java.util.HashSetjava.util.TreeSet
  • Collection沒有索引床蜘,不能直接遍歷辙培,先轉(zhuǎn)換成數(shù)組

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

  • 這些方法可用于操作<mark>所有的</mark>單列集合扬蕊。方法如下:

  • public boolean add(E e): 把給定的對象添加到當(dāng)前集合中 搀别。可以不用接收

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

  • public boolean remove(E e): 把給定的對象在當(dāng)前集合中刪除歇父。

  • public boolean contains(E e): 判斷當(dāng)前集合中是否包含給定的對象。

  • public boolean isEmpty(): 判斷當(dāng)前集合是否為空再愈。

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

  • public Object[] toArray(): 把集合中的元素,存儲到數(shù)組中践磅。

public static void main(String[] args) {
        //多態(tài),接口指向?qū)崿F(xiàn)類
        //此處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);
        //把集合變成數(shù)組
        Object[] array = collection1.toArray();
        //遍歷數(shù)組羔飞,kiana Fuka
        for (int i = 0; i <array.length ; i++) {
            System.out.println(array[i]);
        }
        //刪除集合元素,集合本身還在
        collection1.clear();
        //輸出[]
        System.out.println(collection1);
        }

二檐春、迭代器

Iterator迭代器逻淌,是Collection集合通用的取出元素的方式,先判斷集合有沒有元素疟暖,有就取出一個元素卡儒,再繼續(xù)判斷有沒有元素……直到把集合中所有元素全部取出。這種取出方式稱作迭代俐巴。

boolean <mark>hasNext()</mark>:(判斷)如果仍有元素可以迭代骨望,則返回 true。
E <mark>next()</mark>:(取出)返回迭代的下一個元素欣舵。
void <mark>remove()</mark>:從迭代器指向的 collection 中移除迭代器返回的最后一個元素(可選操作)擎鸠。

Iterator是接口 不能直接使用,需要接口的實(shí)現(xiàn)類缘圈。注意劣光,Iterator接口也是有泛型的,與集合相同糟把。Collection接口里有個方法:
iterator() 绢涡,返回的就是Iterator的實(shí)現(xiàn)類對象。
Iterator <mark>iterator()</mark>: 返回在此 collection 的元素上進(jìn)行迭代的迭代器遣疯。

public static void main(String[] args) {
        Collection<String> collection1 = new ArrayList<>();
        collection1.add("板鴨");
        collection1.add("芽衣");
        //[板鴨, 芽衣]
        System.out.println(collection1);
        //第一步雄可,獲取這個集合的迭代器。接口指向?qū)崿F(xiàn)類對象
        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());
        //已經(jīng)沒有元素了狭归,再取會拋出NoSuchElementException沒有元素異常
//        System.out.println(iterator.next());

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

        }
    }

三夭坪、泛型

  • 泛型:一種未知的數(shù)據(jù)類型文判,定義集合時若暫未確定集合內(nèi)元素類型,可使用泛型室梅。
  • 泛型也可以看作是一個變量戏仓,用來接收數(shù)據(jù)類型。
  • E e:Element 元素
  • T t:Type 類型
  • 創(chuàng)建集合對象的時候亡鼠,就會確認(rèn)泛型的數(shù)據(jù)類型
    *不使用泛型時赏殃,默認(rèn)Object類型,可以存儲任意類型的數(shù)據(jù)间涵。壞處:不安全仁热,會引發(fā)異常。
  • 好處:避免了類型轉(zhuǎn)換的麻煩勾哩;把運(yùn)行期異常抗蠢,提升到了編譯期。
public static void main(String[] args) {
        method1();
        method2();
    }
    /*
    創(chuàng)建集合對象思劳,不使用泛型時迅矛,默認(rèn)Object類型,可以存儲任意類型的數(shù)據(jù)潜叛。
    壞處:不安全秽褒,會引發(fā)異常。
     */
    private static void method1(){
        ArrayList array1 = new ArrayList();//創(chuàng)建集合
        array1.add("女武神");//存儲字符串
        array1.add(12);//存儲整數(shù)
        //使用迭代器遍歷
        Iterator iterator1 = array1.iterator();
        while(iterator1.hasNext()){
            Object obj1 = iterator1.next();
            System.out.println(obj1);//輸出:女武神 12

            //假如要使用String類里的lenghth()輸出字符串長度威兜,
            // 需要把Object類型的obj1向下轉(zhuǎn)型為String類型
            String string1 = (String)obj1;
            System.out.println(string1.length());//3
            //上面產(chǎn)生了ClassCastException類型轉(zhuǎn)換異常销斟,這就是不使用泛型的缺點(diǎn)
        }
    }
    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());
        }
    }

  • 定義一個含有泛型的數(shù)據(jù)類型,模擬ArrayList集合椒舵。
  • 泛型可以接收任意的數(shù)據(jù)類型票堵,可以使用Integer,String逮栅、Object……
  • 創(chuàng)建對象的時候確定泛型的數(shù)據(jù)類型悴势。
  • 不寫泛型默認(rèn)是Object類型
//添加泛型E:
public class Demo05_class<E> {
    private E name;

    public E getName() {
        return name;
    }

    public void setName(E name) {
        this.name = name;
    }
}

  • 測試類
    對象類寫成泛型,不把它寫死措伐,要什么類型就在創(chuàng)建對象的時候定義
 */
public class Demo05_class1 {

    public static void main(String[] args) {
        //不寫泛型默認(rèn)是Object類型
        Demo05_class obj = new Demo05_class();
        obj.setName("字符串");

        //創(chuàng)建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
        //靜態(tài)方法通過類名點(diǎn)方法名直接使用侥加。
        Demo05_method.method2("666");

        //創(chuàng)建接口實(shí)現(xiàn)類對象方法1
        Demo05_InterfaceImpl obj4 = new Demo05_InterfaceImpl();
        obj4.method4("888");
        //創(chuàng)建接口實(shí)現(xiàn)類對象方法2,在創(chuàng)建對象時確認(rèn)泛型
        Demo05_InterfaceImpl2<String> obj5 = new Demo05_InterfaceImpl2();
        obj5.method4("字符串");

    }

  • 定義接口的實(shí)現(xiàn)類,指定接口的泛型
public interface Iterator<E>{
    E next();
}
public class Demo05_InterfaceImpl implements Demo05_Interface<String> {
    @Override
    public void method4(String i){
        System.out.println(i);
    }
}

  • 接口和實(shí)現(xiàn)類后都寫上泛型捧存, 重寫時泛型作為參數(shù)進(jìn)入方法
public class Demo05_InterfaceImpl2<I> implements Demo05_Interface<I> {
    @Override
    public void method4(I i){
        System.out.println("重寫2");
    }

}

  • 定義含有泛型的方法:
    泛型定義在方法的修飾符和返回值之間,參數(shù)列表里可以通過泛型使用
    在調(diào)用方法的時候確認(rèn)泛型的使用類型
public class Demo05_method {

    public <E> void method1(E one) {
        System.out.println(one);
    }
    //定義一個含有泛型的靜態(tài)方法
    public static <S> void method2(S s){
        System.out.println("含有泛型的靜態(tài)方法");
    }
}

  • 泛型通配符<?>在參數(shù)傳遞的時候使用
public static void main(String[] args) {
        ArrayList<String> list1 = new ArrayList<>();
        list1.add("字符串");
        ArrayList<Integer> list2 = new ArrayList<>();
        list2.add(666);
        //該方法能同時調(diào)用不同類型的集合
        method1(list1);//字符串
        method1(list2);//666
    }
    //泛型通配符在參數(shù)傳遞的時候使用
    public static void method1(ArrayList<?> list){
        Iterator<?> iterator1 = list.iterator();
        while(iterator1.hasNext()){
            System.out.println(iterator1.next());
        }
    }

斗地主案例實(shí)現(xiàn)

public static void main(String[] args) {
        //定義存儲54張牌的ArrayList集合
        ArrayList<String> array1 = new ArrayList<>();
        //定義兩個數(shù)組,一個存儲花色昔穴,一個存儲序號
        String[] colors = {"黑桃","紅桃","方塊","梅花"};
        String[] nubers = {"3","4","5","6","7","8","9","10","J","Q","K","A","2"};
        //集合里存儲大王小王
        array1.add("大王");
        array1.add("小王");
        //循環(huán)嵌套兩個數(shù)組镰官,組裝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<>();
        //發(fā)牌
        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發(fā)牌
                play01.add(str1);
            }else if (i%3==1){
                //玩家2發(fā)牌
                play02.add(str1);
            }else if (i%3==2){
                //玩家3發(fā)牌
                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集合下的實(shí)現(xiàn)類中宙搬,ArrayList查找快笨腥,增刪慢;LinkedList是List借口的鏈表實(shí)現(xiàn)勇垛,查詢慢脖母,增刪快。

import java.util.List;

  • List:有序集合(存取順序相同)闲孤,有索引谆级,允許存儲重復(fù)元素。底層是數(shù)組讼积。此實(shí)現(xiàn)是多線程肥照,非同步。
  • 方法:
    boolean <mark>add(E e)</mark>
    向列表的尾部添加指定的元素(可選操作)币砂。
    void <mark>add</mark>(int index, E element)
    在列表的指定位置插入指定元素(可選操作)建峭。
    E <mark>get</mark>(int index)
    返回列表中指定位置的元素。
    ListIterator <mark>listIterator()</mark>
    返回此列表元素的列表迭代器(按適當(dāng)順序)决摧。
    ListIterator <mark>istIterator(int index)</mark>
    返回列表中元素的列表迭代器(按適當(dāng)順序)亿蒸,從列表的指定位置開始。
    E <mark>remove</mark>(int index)
    移除列表中指定位置的元素(可選操作)掌桩。
    boolean <mark>remove</mark>(Object o)
    從此列表中移除第一次出現(xiàn)的指定元素(如果存在)(可選操作)边锁。
public static void main(String[] args) {
        //多態(tài)
        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);//[翼, 展, 開]

    }

實(shí)現(xiàn)類LinkedList

  • LinkedList集合查詢慢,增刪快波岛,含有大量用于修改首尾的方法茅坛。
    如果使用LinkedList特有的方法,則不能使用多態(tài)
  • 方法:
    void <mark>addFirst</mark>(E e):
    將指定元素插入此列表的開頭则拷。
    void <mark>addLast</mark>(E e):
    將指定元素添加到此列表的結(jié)尾贡蓖。
    void <mark>clear()</mark>:
    從此列表中移除所有元素。
    boolean <mark>contains</mark>(Object o):
    如果此列表包含指定元素煌茬,則返回 true斥铺。
    E <mark>get</mark>(int index):
    返回此列表中指定位置處的元素。
    E <mark>getFirst</mark>():
    返回此列表的第一個元素坛善。
    E <mark>getLast()</mark>:
    返回此列表的最后一個元素晾蜘。
    E <mark>removeFirst()</mark>:
    移除并返回此列表的第一個元素邻眷。
    E <mark>removeLast()</mark>:
    移除并返回此列表的最后一個元素。
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("含有l(wèi)ova");
        }
        list1.removeFirst();
        System.out.println(list1);//[kiana, is me]
    }

  • Vector集合剔交,實(shí)現(xiàn)可增長的對象數(shù)組肆饶,底層是數(shù)組,已經(jīng)被ArrayList取代岖常,單線程

五驯镊、Set接口

Collection的另一個孩子,

1.不能存儲重復(fù)元素腥椒。
2.沒有索引阿宅,不能使用普通的for循環(huán)遍歷候衍。
3.底層是哈希表結(jié)構(gòu)笼蛛,查詢速度很快,存取元素順序可能不一致蛉鹿。
4.HashSet集合類實(shí)現(xiàn)Set接口滨砍;

  • 方法:
    boolean <mark>add</mark>(E e):
    如果 set 中尚未存在指定的元素,則添加此元素(可選操作)妖异。
    boolean <mark>addAll</mark>(Collection<? extends E> c):
    如果 set 中沒有指定 collection 中的所有元素惋戏,則將其添加到此 set 中(可選操作)。
    void <mark>clear</mark>():
    移除此 set 中的所有元素(可選操作)他膳。
    boolean <mark>contains</mark>(Object o):
    如果 set 包含指定的元素响逢,則返回 true。
    boolean <mark>containsAll</mark>(Collection<?> c):
    如果此 set 包含指定 collection 的所有元素棕孙,則返回 true舔亭。
    boolean <mark>equals</mark>(Object o):
    比較指定對象與此 set 的相等性。
    int <mark>hashCode</mark>():
    返回 set 的哈希碼值蟀俊。
    boolean <mark>isEmpty</mark>():
    如果 set 不包含元素钦铺,則返回 true。
    Iterator <mark>iterator()</mark>:
    返回在此 set 中的元素上進(jìn)行迭代的迭代器肢预。
    boolean <mark>remove(Object o)</mark>:
    如果 set 中存在指定的元素矛洞,則將其移除(可選操作)。
    boolean <mark>removeAll</mark>(Collection<?> c):
    移除 set 中那些包含在指定 collection 中的元素(可選操作)烫映。
    boolean <mark>retainAll</mark>(Collection<?> c):
    僅保留 set 中那些包含在指定 collection 中的元素(可選操作)沼本。
    int <mark>size</mark>():
    返回 set 中的元素數(shù)(其容量)。
    Object[] <mark>toArray</mark>():
    返回一個包含 set 中所有元素的數(shù)組锭沟。
    T[] <mark>toArray</mark>(T[] a):
    返回一個包含此 set 中所有元素的數(shù)組抽兆;返回數(shù)組的運(yùn)行時類型是指定數(shù)組的類型。
public static void main(String[] args) {
        Set<String> setList1 = new HashSet<>();
        setList1.add("Mei");
        setList1.add("逐火之蛾");
        setList1.add("Mei");//重復(fù)元素存儲失敗
        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實(shí)現(xiàn)類

  • 哈希值是一個十進(jìn)制的整數(shù)冈钦,由系統(tǒng)隨機(jī)給出郊丛。
    Object類的hashCode方法返回對象的哈希碼值:
    int <mark>hashCode()</mark>
    jdk1.8之后李请,哈希表=數(shù)組+紅黑樹(加快查詢速度)
    存儲數(shù)據(jù)到集合中,首先計算元素的哈希值
  • 沒有重寫時厉熟,HashSet比較的是兩個對象的地址值导盅,
    存儲自定義類型的元素時必須重寫hashCode和equals方法同時比較元素和哈希值更穩(wěn)妥。
    按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)

  • 具有可預(yù)知迭代順序的Set接口的哈希表和鏈表實(shí)現(xiàn)
    LinkedHashSet集合extends了HashSet集合,
    LinkedHashSet集合底層是哈希表(鏈表+數(shù)組/紅黑樹)+鏈表揍瑟,多的鏈表用來記錄元素存儲順序白翻,保證元素有序
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],無重復(fù),無順序

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

六滤馍、可變參數(shù)

  • 可變參數(shù):當(dāng)方法的參數(shù)列表數(shù)據(jù)類型已經(jīng)確定,但參數(shù)的數(shù)據(jù)類型不確定底循,就可以使用可變參數(shù)
    使用格式:定義方法時使用
    修飾符 返回值類型 方法名(數(shù)據(jù)類型…變量名){}
    原理:可變參數(shù)底層是數(shù)組巢株,根據(jù)傳遞參數(shù)個數(shù)不同,會創(chuàng)建不同長度的數(shù)組熙涤,來存儲這些參數(shù)阁苞。
    傳遞的參數(shù)個數(shù)可以是0個(不傳遞),1,2祠挫,3…很多個那槽。
    可變參數(shù)的終極寫法:
    (Object…obj)
  • 注意:
    一個方法的參數(shù)列表,只能有一個可變參數(shù)等舔。
    如果方法的參數(shù)有多個骚灸,那么可變參數(shù)必須寫在參數(shù)列表的末尾。
public static void main(String[] args) {
        Sum1();
        System.out.println(Sum2(222,111,223,3));//559
        Sum3(33,"w",3.14);
    }
    //定義一個方法慌植,計算兩個int整數(shù)的和
    public static void Sum1(){
        System.out.println("請輸入倆數(shù)字");
        Scanner num1 = new Scanner(System.in);
        Scanner num2 = new Scanner(System.in);
        int sum = num1.nextInt()+num2.nextInt();
        System.out.println(sum);
    }
    //計算未定數(shù)目的參數(shù)的和
    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 <mark>boolean addAll</mark>(Collection c,T…elements)
    往集合中添加多個元素
    public static void <mark>shuffle</mark>(List list)
    打亂集合順序
    public static void <mark>sort</mark>(List list)
    將集合中的元素按照默認(rèn)順序排序
    public static void <mark>sort</mark>(List list,Comparator <? super T>)
    將集合中的元素按照指定規(guī)則排序
  • 注:被排序的集合里的元素,必須實(shí)現(xiàn)Comparable接口涤浇,重寫接口中的compareTo定義排序的規(guī)則
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默認(rèn)(數(shù)字默認(rèn)大小升序鳖藕,字符串默認(rèn)自然升序abcdefg...)
        Collections.sort(list1);
        System.out.println("默認(rèn)排序后:"+list1);//[a, a, i, k, n]
        //sort指定,重寫排序規(guī)則
        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);

八、集合數(shù)據(jù)結(jié)構(gòu)

和集合相關(guān)的數(shù)據(jù)結(jié)構(gòu):棧蜻展、隊列喉誊,數(shù)組,鏈表纵顾,紅黑樹伍茄。

  • 棧:先進(jìn)后出
    元素存儲到集合中時,先存儲的元素在棧的底部施逾,后進(jìn)入的元素在棧的頂部敷矫,
    取出元素時例获,先取出棧頂部的元素,棧底部的元素后取出曹仗。棧的出口和入口相同榨汤。
    例如:入棧順序123,出棧的順序即為321怎茫。

  • 隊列:先進(jìn)先出
    入口和出口不同收壕,先入者接近出口,后入者離出口較遠(yuǎn)轨蛤。

  • 數(shù)組:查詢快蜜宪,增刪慢。
    查詢快:數(shù)組的地址是連續(xù)的祥山,通過首地址找到數(shù)組圃验,再通過索引找到想要的數(shù)組元素。
    增刪慢:數(shù)組的長度是固定的枪蘑,增刪數(shù)組需要創(chuàng)建一個新的數(shù)組损谦,并將源數(shù)組的數(shù)據(jù)復(fù)制到新數(shù)組中岖免。
    源數(shù)組在內(nèi)存中被銷毀(垃圾回收)岳颇。

  • 鏈表(linked list):由一系列節(jié)點(diǎn)node(鏈表中的元素)組成,節(jié)點(diǎn)在運(yùn)行時動態(tài)生成颅湘。
    每個節(jié)點(diǎn)包含一個存儲數(shù)據(jù)元素的數(shù)據(jù)域话侧,和兩個分別存儲自己和下一個節(jié)點(diǎn)地址的指針域。
    鏈表結(jié)構(gòu)通常有單向鏈表和雙向鏈表闯参。多個節(jié)點(diǎn)間通過地址相連瞻鹏。
  • 單向鏈表:鏈表中只有一條鏈子,不能保證元素的順序鹿寨。存儲新博、取出的數(shù)據(jù)可能不一致。
  • 雙向鏈表:有兩條鏈子脚草,其中一條專門記錄元素的順序赫悄,所是一個有序的集合.
    查詢慢:想查找某個元素,需要通過連接的節(jié)點(diǎn)馏慨,一次向后查找指定元素埂淮。地址不連續(xù),每次查詢需要從頭開始写隶。
    增刪快:增刪元素對鏈表整體結(jié)構(gòu)沒有影響倔撞,所以快。

  • 紅黑樹:
    二叉樹:分支不能超過兩格的樹
    排序樹/查找樹:在二叉樹的基礎(chǔ)上慕趴,元素是有大小的痪蝇,左子樹小鄙陡,右子樹大
    紅黑樹:節(jié)點(diǎn)紅色或黑色,根節(jié)點(diǎn)黑色躏啰,葉子節(jié)點(diǎn)黑色柔吼,每個紅色的節(jié)點(diǎn)的子節(jié)點(diǎn)都是黑色,任何節(jié)點(diǎn)到其
    每一個葉子節(jié)點(diǎn)的所有路徑上黑色節(jié)點(diǎn)的數(shù)量是相同的丙唧。

九愈魏、Map集合接口

java里集合除了Collections(List/Set)外就是Map集合,用來存放映射關(guān)系的對象想际。

  • Collection中的集合培漏,元素是孤立存在的(理解為單身),向集合中存儲元素采用一個個元素的方式存儲胡本。
  • Map 中的集合牌柄,元素是成對存在的(理解為夫妻)。每個元素由鍵與值兩部分組成侧甫,通過鍵可以找對所對應(yīng)的值珊佣。
  • Collection 中的集合稱為單列集合, Map 中的集合稱為雙列集合披粟。
    需要注意的是咒锻, Map 中的集合不能包含重復(fù)的鍵,值可以重復(fù)守屉;每個鍵只能對應(yīng)一個值惑艇。
  • java.util.Map<k,v> :key鍵,value值拇泛,通過key可以找到對應(yīng)的value滨巴,
    value可以重復(fù),一個key對應(yīng)一個value俺叭,key不可以重復(fù)恭取。
    key和map數(shù)據(jù)類型可以相同可以不同,
    靠key維護(hù)他們之間的關(guān)系熄守。

HashMap:

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

  • HashMap:存儲數(shù)據(jù)采用的哈希表結(jié)構(gòu)蜈垮,元素的存取順序不能保證一致。
    由于要保證鍵的唯一柠横、不重復(fù)窃款,需 要重寫鍵的hashCode()方法、equals()方法牍氛。
  • LinkedHashMap:HashMap下有個子類LinkedHashMap晨继,存儲數(shù)據(jù)采用的哈希表結(jié)構(gòu)+鏈表結(jié)構(gòu)。
    通過鏈表結(jié)構(gòu)可以保證元素的存取順序一致搬俊;通過哈希表結(jié)構(gòu)可以保證的鍵的唯一紊扬、不重復(fù)蜒茄,
    需要重寫鍵的 hashCode()方法、equals()方法餐屎。

tips:Map接口中的集合都有兩個泛型變量,在使用時檀葛,要為兩個泛型變量賦予數(shù)據(jù)類型。
兩個泛型變量的數(shù) 據(jù)類型可以相同腹缩,也可以不同屿聋。
tips:Map集合不能直接使用迭代器或者foreach進(jìn)行遍歷。但是轉(zhuǎn)成Set之后就可以使用了藏鹊。

Map接口中定義了很多方法润讥,常用的如下:
public V <mark>put</mark>(K key, V value) : 把指定的鍵與指定的值添加到Map集合中。
public V <mark>remove</mark>(Object key) : 把指定的鍵 所對應(yīng)的鍵值對元素 在Map集合中刪除盘寡,返回被刪除元素的值楚殿。
public V <mark>get</mark>(Object key) 根據(jù)指定的鍵,在Map集合中獲取對應(yīng)的值竿痰。
public Set <mark>keySet</mark>() : 獲取Map集合中所有的鍵脆粥,存儲到Set集合中。
public Set<Map.Entry<K,V>> <mark>entrySet</mark>() : 獲取到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或者增強(qiáng)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+" 對應(yīng) "+value);

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

Entry:

Map 中存放的是兩種對象常潮,一種稱為key(鍵)弟胀,一種稱為value(值),
它們在在 Map 中是一一對應(yīng)關(guān)系喊式,這一對對象又稱做 Map 中的一個 Entry(項)
Entry 將鍵值對的對應(yīng)關(guān)系封裝成了對象。
即鍵值對對象萧朝,這樣我們在
遍歷 Map 集合時岔留,就可以從每一個鍵值對( Entry )對象中獲取對應(yīng)的鍵與對應(yīng)的值。
既然Entry表示了一對鍵和值检柬,那么也同樣提供了

  • 獲取對應(yīng)鍵和對應(yīng)值的方法:
    public K <mark>getKey</mark>() :獲取Entry對象中的鍵献联。
    public V <mark>getValue()</mark> :獲取Entry對象中的值。
    在Map集合中也提供了
  • 獲取所有Entry對象的方法:
    public Set<Map.Entry<K,V>> <mark>entrySet</mark>() : 獲取到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();
        //增強(qiáng)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集合存儲自定義類型的方法:
    當(dāng)給HashMap中存放自定義對象時用爪,
    如果自定義對象作為key存在原押,
    這時要保證對象唯一,必須復(fù)寫對象的 hashCode和equals方法.
    如果要保證map中存放的key和取出的順序一致偎血,可以使用 java.util.LinkedHashMap 集合來存放诸衔。
public static void main(String[] args) {
        //key寫為自定義類型
        HashMap<Dem00_Person,String> map1 = new HashMap<>();
        //創(chuàng)建自定義對象為參數(shù):
        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();

集合工廠方法 <mark>of</mark>():

  • JDK9對集合添加元素的優(yōu)化:
    通常,我們在代碼中創(chuàng)建一個集合(例如笨农,List 或 Set )就缆,并直接用一些元素填充它。
    實(shí)例化集合谒亦,幾個 add方法 調(diào)用竭宰,代碼顯得重復(fù)。
    Java 9份招,添加了幾種集合工廠方法,更方便創(chuàng)建少量元素的集合羞延、map實(shí)例。
    新的List脾还、Set伴箩、Map的靜態(tài)工廠方法of可以更方便地創(chuàng)建集合的不可變實(shí)例。
  • 使用前提:
    1.集合中元素的數(shù)確定且不再改變
    2.只適用于List鄙漏、Set嗤谚、Map接口,不適用于它們的實(shí)現(xiàn)類怔蚌;
    3.Set和Map存的元素不能有重復(fù),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集合存儲重復(fù)元素,拋出IllegalArgumentException非法參數(shù)異常
    }

十桦踊、Debug

IDEA中:
左邊設(shè)置斷點(diǎn)椅野,右鍵選擇Debug運(yùn)行程序,程序停止在了斷點(diǎn)行不再運(yùn)行
Debug后籍胯,下方按鈕從左到右:

  • Console:切換到控制臺
  • Step Over(F8):代碼向下執(zhí)行一行
  • Step Into(F7):進(jìn)入要調(diào)用的方法
  • Step Out(shift + F8):跳出方法
    左邊:
  • Resume Program(F9):調(diào)到下一個斷點(diǎn)
  • Stop(Ctrl+F2):停止調(diào)試的程序竟闪,退出Debug模式
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市杖狼,隨后出現(xiàn)的幾起案子炼蛤,更是在濱河造成了極大的恐慌,老刑警劉巖蝶涩,帶你破解...
    沈念sama閱讀 216,544評論 6 501
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件理朋,死亡現(xiàn)場離奇詭異,居然都是意外死亡绿聘,警方通過查閱死者的電腦和手機(jī)嗽上,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,430評論 3 392
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來熄攘,“玉大人兽愤,你說我怎么就攤上這事。” “怎么了烹看?”我有些...
    開封第一講書人閱讀 162,764評論 0 353
  • 文/不壞的土叔 我叫張陵国拇,是天一觀的道長。 經(jīng)常有香客問我惯殊,道長酱吝,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,193評論 1 292
  • 正文 為了忘掉前任土思,我火速辦了婚禮务热,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘己儒。我一直安慰自己崎岂,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,216評論 6 388
  • 文/花漫 我一把揭開白布闪湾。 她就那樣靜靜地躺著冲甘,像睡著了一般。 火紅的嫁衣襯著肌膚如雪途样。 梳的紋絲不亂的頭發(fā)上江醇,一...
    開封第一講書人閱讀 51,182評論 1 299
  • 那天,我揣著相機(jī)與錄音何暇,去河邊找鬼陶夜。 笑死,一個胖子當(dāng)著我的面吹牛裆站,可吹牛的內(nèi)容都是我干的条辟。 我是一名探鬼主播,決...
    沈念sama閱讀 40,063評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼宏胯,長吁一口氣:“原來是場噩夢啊……” “哼羽嫡!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起胳嘲,我...
    開封第一講書人閱讀 38,917評論 0 274
  • 序言:老撾萬榮一對情侶失蹤厂僧,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后了牛,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,329評論 1 310
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡辰妙,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,543評論 2 332
  • 正文 我和宋清朗相戀三年鹰祸,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片密浑。...
    茶點(diǎn)故事閱讀 39,722評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡蛙婴,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出尔破,到底是詐尸還是另有隱情街图,我是刑警寧澤浇衬,帶...
    沈念sama閱讀 35,425評論 5 343
  • 正文 年R本政府宣布,位于F島的核電站餐济,受9級特大地震影響耘擂,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜絮姆,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,019評論 3 326
  • 文/蒙蒙 一醉冤、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧篙悯,春花似錦蚁阳、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,671評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至矮燎,卻和暖如春定血,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背漏峰。 一陣腳步聲響...
    開封第一講書人閱讀 32,825評論 1 269
  • 我被黑心中介騙來泰國打工糠悼, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人浅乔。 一個月前我還...
    沈念sama閱讀 47,729評論 2 368
  • 正文 我出身青樓倔喂,卻偏偏與公主長得像,于是被迫代替她去往敵國和親靖苇。 傳聞我的和親對象是個殘疾皇子席噩,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,614評論 2 353

推薦閱讀更多精彩內(nèi)容

  • 四、集合框架 1:String類:字符串(重點(diǎn)) (1)多個字符組成的一個序列贤壁,叫字符串悼枢。生活中很多數(shù)據(jù)的描述都采...
    佘大將軍閱讀 752評論 0 2
  • 一、基礎(chǔ)知識:1脾拆、JVM馒索、JRE和JDK的區(qū)別:JVM(Java Virtual Machine):java虛擬機(jī)...
    殺小賊閱讀 2,378評論 0 4
  • 集合類簡介 為什么出現(xiàn)集合類渠驼?面向?qū)ο笳Z言對事物的體現(xiàn)都是以對象的形式胀蛮,所以為了方便對多個對象的操作裕便,就要對對象進(jìn)...
    阿敏其人閱讀 1,417評論 0 7
  • Java集合類可用于存儲數(shù)量不等的對象,并可以實(shí)現(xiàn)常用的數(shù)據(jù)結(jié)構(gòu)如棧,隊列等,Java集合還可以用于保存具有映射關(guān)...
    小徐andorid閱讀 1,939評論 0 13
  • 轉(zhuǎn)載自:Java集合框架實(shí)例 1- 介紹 集合是程序和語言的基本思想贝室。應(yīng)用程序通常都會應(yīng)用到集合半沽,例如雇員的信息,...
    01_小小魚_01閱讀 397評論 0 1