java學習(八)-集合與泛型

1、裝箱和拆箱

在這裏插入圖片描述
在這裏插入圖片描述

2、封裝類的使用1,是作爲泛型的類型參數傳入
  • ArrayList類型的聲明是正確的。ArrayList聲明是錯誤的。因爲泛型的規則是你只能指定類和接口類型。後面那種聲明方法無法通過編譯
3、集合
  • ArrayList:
  • LinkedList:針對經常插入或者刪除中獎元素所涉及的高效率集合
  • HashMap:存取較高效,是用成對的key/value的形式來保存和取出
  • LinkedHashMap:類似HashMap。但可記住元素插入的順序,也可以設定成依照元素上次存取的先後來排序
  • TreeSet:以有序狀態保持並可放在重複,當往集合中存儲元素的時候,會花一定的時間去找合適的 位置(即是排序),如果是對順序沒有要求的,用ArrayList集合更高效
  • HashSet:防止重複的集合,可快速查找相符的元素
4、泛型,泛型接口:list、map、set等
  • 泛型意味着更好的類型安全性。運用泛型,你可以創建類型安全更好的集合,讓問題儘可能的在編譯階段就能抓到,而不會是在執行期間才被發現;若不是泛型的集合,則編譯器會很樂意接受你不同類型的對象放在同一個集合中。
  • 泛型的使用1:創建被泛型化類的實例new ArrayList<Song>()
  • 泛型的使用2:聲明與指定泛型類型的變量List<Song> songList = new ArrayList<Song>()
  • 泛型的使用3:聲明或調用取用泛型類型的方法void foo(List<Song> list)、x.foo(songList)
  • 泛型接口:List、Map、Set
4.1、泛型的好處

泛型的好處是在編譯的時候檢查類型安全並且所有的強制轉換都是自動和隱式的,提高代碼的重用率。

  • 類型安全,主要目標是提高 Java 程序的類型安全。
  • 消除強制類型轉換。
5、一些常用說法
  • ArrayList也可以通過指定位置的方式在集合中添加元素。但是這種會比較慢。
  • Collections.sort(stringList)會把stringList中的String依照字母排序。但是若Collections.sort(songList),songList是一個對象類型的集合,此時是不允許編譯通過的。Collections的sort方法定義爲public static <T extends Comparable<? super T.> void sort(List<T> list),這個說明sort只能接口Comparable對象的list,而Song不是Comparable的子型,所以無法進行排序,編譯不通過。
6、comparable與comparator
  • 調用單一參數的sort(List o)方法代表有list元素的compareTo()方法來決定順序,因此元素必須實現Comparable的接口
  • 調用sort(List o, Comparator c)方法代表不會調用list元素的compareTo()的方法,而會調用Comparaotr的compare()方法,這意味着list元素不需要實現Comparable接口
    注意:不是所有的類都需要實現Comparable接口的,會讓人誤解。
7、對象的等價
7.1、set將兩個對象視爲重複:
  • x.equals(y)返回true
  • x的hashCode與y的hashCode相等;滿足這兩個條件,視爲重複對象
7.2、相等性
  • 引用相等性,使用==來比較變量的字節組合。如果引用到相同的對象,字節組合會一樣
  • 對象相等性:(x.equals(y)) && (x.hashCode() == y.hashCode())(對象必須覆蓋過object的hashCode方法,不然因爲大部分的java版本是依據內存位置來計算hashCode方法返回的序號值,一般都會不一樣。所以需要重寫,,才能確保兩個對象有相同的hashCode);
  • x.equals(y)返回true,則x.hashCode()==y.hashCode()等值
  • x.hashCode()==y.hashCode()等值,但是 x.equals(y)不一定會返回true;由於hash算法有可能會發生碰撞,不同的值可能會返回相同的hashCode值。
8、TreeSet的元素是有序列表,必須有方法來排序。
  • 集合中的元素必須是有實現Comparable的類型,通過實現它的compareTo的方法進行排序
  • 使用重載,調用Comparator參數的構造器來創建TreeSet。通過compator的實現類的compare方法進行排序
9、參數化類型
  • 普通的參數化類型,可以支持參數化的向上轉型,即父類引用指向子類的實例對象
public void go5(){
        Animal animal = new Animal();
        Dog dog = new Dog();
        takeAnimals5(dog);//向上轉型,把子類的對象直接賦給父類的引用,成功的
        takeAnimals6(animal);//會報錯,編譯不通過
        takeAnimals6((Dog) animal);
    }

    public void takeAnimals5(Animal animal){
    }

    public void takeAnimals6(Dog dog){

    }
  • 數組類型的參數化傳遞
    數組類型校驗是在允許階段,編譯會通過
public void go(){
        Animal[] animals = {new Dog(),new Cat(),new Dog()};
        Dog[] dogs = {new Dog(),new Dog(),new Dog()};
        takeAnimals(animals);
        takeAnimals(dogs);
    }

    public void takeAnimals(Animal[] animals){
        for (Animal a:animals){
            a.eat();
        }

    }
public void go3(){
        Dog[] dogs = {new Dog(),new Dog(),new Dog()};
        takeAnimals3(dogs);
    }

    public void takeAnimals3(Animal[] animals){
        //編譯通過,但是執行會報錯,因爲數組的類型校驗是運行期間,不允許往dog類型的數組裏添加Cat類型的對象
        animals[0] = new Cat();

    }
  • 集合參數類型的傳遞,只能是一一對應的關係
    集合類型的參數校驗是在編譯階段就進行校驗
public void go2(){
        ArrayList<Animal> animals = new ArrayList<Animal>();
        animals.add(new Dog());
        animals.add(new Cat());
        animals.add(new Dog());

        ArrayList<Dog> dogs = new ArrayList<Dog>();
        dogs.add(new Dog());
        dogs.add(new Dog());

        takeAnimals2(animals);
        //編譯報錯,由於集合的類型校驗,是在編譯期間。集合參數化,只能是一一對應的關係。
        takeAnimals2(dogs);//編譯不通過
        takeAnimals4(animals);//編譯不通過
        takeAnimals4(dogs);
        takeAnimals7(animals);
        takeAnimals7(dogs);
    }

    public void takeAnimals2(ArrayList<Animal> animals){
        for (Animal a:animals){
            a.eat();
        }
    }
    public void takeAnimals4(ArrayList<Dog> dogs){
        for (Dog a:dogs){
            a.eat();
        }
    }
    //採用萬能字符實現多態化集合參數類型的校驗
    public void takeAnimals7(ArrayList<? extends Animal> animals){
        for (Animal a:animals){
            a.eat();
        }
    }
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章