Java第十六天(泛型、Set接口、可變參數、數組工具類、集合工具類)

72.泛型java

(1)概念面試

泛型就是在集合中指定存儲的數據類型,並且只能存儲這種類型,在List<類型>必需要指定, ArrayList<>能夠指定也能夠不指定。基本數據類不能做爲泛型。數組

import java.util.ArrayList;
import java.util.List;
import java.util.ListIterator;

public class Generic {
    public static void main(String[] args) {
        //指定集合中只能存儲一種數據類型
        List<Person> list = new ArrayList<>();
        Person p=new Person("frank",12);
        Person p1=new Person("lisa",11);
        list.add(p);
        list.add(p1);
        List<Person> list1 = new ArrayList<>();
        //age的int類型自動轉成Integer類型
        Student s=new Student("david",11,1);
        Student s1=new Student("mia",12,2);
        //指定存儲person的集合中能夠存儲指定類型和它的子類
        list1.add(s);
        list1.add(s1);
        //指定存儲person的集合中能夠存儲指定類型和存儲它的子類的子集合
        list.addAll(list1);
        ////建立一個迭代器對象
        ListIterator<Person> personListIterator = list.listIterator();
        while(personListIterator.hasNext()){
            //得到到Person型
            Person next = personListIterator.next();
            System.out.println(next);
        }
    }
}

(2)自定義泛型安全

在自定義泛型時併發

語法:class/interface 類名/接口名 <T>{ide

 

}函數

T只是泛型的一個標準,使用什麼字符均可以,可是都要大寫,不要使用特殊字符,建議用T工具

自定義泛型類性能

public class GenericClass<T> {
    //定義一個泛型的屬性
    private T t;

    public T getT() {
        return t;
    }

    public void setT(T t) {
        this.t = t;
    }
}
public class GenericClass1<T,E,Z> {
    //定義三個泛型的屬性
    private T t;
    private E e;
    private Z z;

    public T getT() {
        return t;
    }

    public void setT(T t) {
        this.t = t;
    }

    public E getE() {
        return e;
    }

    public void setE(E e) {
        this.e = e;
    }

    public Z getZ() {
        return z;
    }

    public void setZ(Z z) {
        this.z = z;
    }

    @Override
    public String toString() {
        return "GenericClass1{" +
                "t=" + t +
                ", e=" + e +
                ", z=" + z +
                '}';
    }
}
import java.util.Arrays;
import java.util.Date;

public class GenericTest {
    public static void main(String[] args) {
        //指定泛型是String
        GenericClass<String> g = new GenericClass<>();
        g.setT("eric");
        System.out.println(g.getT());
        //指定泛型是Integer
        GenericClass<Integer> g1 = new GenericClass<>();
        g1.setT(12);
        System.out.println(g1.getT());
        //指定泛型是Integer數組
        GenericClass<Integer[]> g2 = new GenericClass<>();
        g2.setT(new Integer[]{1,2,3});
        System.out.println(Arrays.toString(g2.getT()));

        //測試3個泛型
        GenericClass1<Person, Integer, Date> g3 = new GenericClass1<>();
        g3.setT(new Person("milk",12));
        g3.setE(1);
        g3.setZ(new Date());
        System.out.println(g3);
    }
}

73.加強for循環測試

在Jdk1.5之後出現了加強的for

對數組,集合來作遍歷

語法:

for(數據類型 變量:集合變量){

///

}

數據類型是集合或者數組中的數的類型

import java.util.ArrayList;
import java.util.List;

public class ForDemo {
    public static void main(String[] args) {
        String[] str={"pop","qoq","mom","bob"};
        System.out.println("-------------數組遍歷----------------");
        for (String s : str) {
            System.out.println(s);
        }
        List<String> list=new ArrayList<>();
        list.add("pop");
        list.add("bop");
        list.add("pop");
        list.add("pop");
        System.out.println("-------------集合遍歷----------------");
        for (String s : list) {
            System.out.println(s);
            if(s.equals("bop")){
                s="bob";
            }
        }
        System.out.println("-------------普通for循環遍歷----------------");
        for (int i = 0; i < list.size(); i++) {
            System.out.println(list.get(i));
            if(list.get(i).equals("bop")){
                list.add("mom");
            }
        }
    }
}

加強的for循環遍歷不支持併發,不能夠增長或者刪除改變集合或者數組的長度會出現異常報錯,可是能夠對某個成分進行更改,編譯運行滅有出現錯誤,可是對結果卻沒有任何影響

普通的for循環能夠實現併發

 

74.Set接口

一個不包含重複元素的 collection。更確切地講,set 不包含知足 e1.equals(e2) 的元素對 e1e2,而且最多包含一個 null 元素。正如其名稱所暗示的,此接口模仿了數學上的 set 抽象。

在全部構造方法以及 add、equals 和 hashCode 方法的協定上,Set 接口還加入了其餘規定,這些規定超出了從 Collection 接口所繼承的內容。出於方便考慮,它還包括了其餘繼承方法的聲明(這些聲明的規範已經專門針對 Set 接口進行了修改,可是沒有包含任何其餘的規定)。

對這些構造方法的其餘規定是(不要奇怪),全部構造方法必須建立一個不包含重複元素的 set(正如上面所定義的)。

注:若是將可變對象用做 set 元素,那麼必須極其當心。若是對象是 set 中某個元素,以一種影響 equals 比較的方式改變對象的值,那麼 set 的行爲就是不肯定的。此項禁止的一個特殊狀況是不容許某個 set 包含其自身做爲元素。

某些 set 實現對其所包含的元素有所限制。例如,某些實現禁止 null 元素,而某些則對其元素的類型全部限制。試圖添加不合格的元素會拋出未經檢查的異常,一般是 NullPointerException 或 ClassCastException。試圖查詢不合格的元素是否存在可能會拋出異常,也可能簡單地返回 false;某些實現會採用前一種行爲,而某些則採用後者。歸納地說,試圖對不合格元素執行操做時,若是完成該操做後不會致使在 set 中插入不合格的元素,則該操做可能拋出一個異常,也可能成功,這取決於實現的選擇。此接口的規範中將這樣的異常標記爲「可選」。

(1)HashSet

此類實現 Set 接口,由哈希表(其實是一個 HashMap 實例)支持。它不保證 set 的迭代順序;特別是它不保證該順序恆久不變。此類容許使用 null 元素。

此類爲基本操做提供了穩定性能,這些基本操做包括 add、remove、contains 和 size,假定哈希函數將這些元素正確地分佈在桶中。對此 set 進行迭代所需的時間與 HashSet 實例的大小(元素的數量)和底層 HashMap 實例(桶的數量)的「容量」的和成比例。所以,若是迭代性能很重要,則不要將初始容量設置得過高(或將加載因子設置得過低)。

注意,此實現不是同步的。若是多個線程同時訪問一個哈希 set,而其中至少一個線程修改了該 set,那麼它必須 保持外部同步。這一般是經過對天然封裝該 set 的對象執行同步操做來完成的。若是不存在這樣的對象,則應該使用 Collections.synchronizedSet 方法來「包裝」 set。最好在建立時完成這一操做,以防止對該 set 進行意外的不一樣步訪問:

Set s = Collections.synchronizedSet(new HashSet(...));

此類的 iterator 方法返回的迭代器是快速失敗 的:在建立迭代器以後,若是對 set 進行修改,除非經過迭代器自身的 remove 方法,不然在任什麼時候間以任何方式對其進行修改,Iterator 都將拋出 ConcurrentModificationException。所以,面對併發的修改,迭代器很快就會徹底失敗,而不冒未來在某個不肯定時間發生任意不肯定行爲的風險。

注意,迭代器的快速失敗行爲沒法獲得保證,由於通常來講,不可能對是否出現不一樣步併發修改作出任何硬性保證。快速失敗迭代器在盡最大努力拋出 ConcurrentModificationException。所以,爲提升這類迭代器的正確性而編寫一個依賴於此異常的程序是錯誤作法:迭代器的快速失敗行爲應該僅用於檢測 bug。

特色:

1.元素惟一性

2.無序行

3.容許null存在一個

4.不是線程安全(效率高)

import java.util.HashSet;
import java.util.Set;

public class SetTest {
    public static void main(String[] args) {
        Set<String> set=new HashSet<>();
        set.add("玉米");
        set.add("花生");
        set.add(null);
        set.add(null);
        System.out.println(set);
    }
}

探究惟一性:

若是對象的hash值和equals都相等那麼就是重複的對象。

import java.util.HashSet;

public class SetTest1 {
    public static void main(String[] args) {
        HashSet<Person> h=new HashSet<>();
        h.add(new Person("Bob",12));
        h.add(new Person("Vob",12));
        h.add(new Person("Sob",12));
        h.add(new Person("Bob",12));
        System.out.println(h);
    }
}

(2)LinkedHashSet

有順序可是應用的很少

具備可預知迭代順序的 Set 接口的哈希表和連接列表實現。此實現與 HashSet 的不一樣以外在於,後者維護着一個運行於全部條目的雙重連接列表。此連接列表定義了迭代順序,即按照將元素插入到 set 中的順序(插入順序)進行迭代。注意,插入順序 受在 set 中從新插入的 元素的影響。(若是在 s.contains(e) 返回 true 後當即調用 s.add(e),則元素 e 會被從新插入到 set s 中。)

(3)TreeSet

字符串的比較規則是先按照第一個字符來比較,若是一個字符串的第一個字符比另外一個字符串首字符大,那前者大。

compareTo方法返回的是整數便是前者大,返回負數是後者大,是0就是相等

類若是要實現比較的規則都會實現Comparable接口。能夠重寫compareTo方法自定義比較規則

public class Person implements Comparable{
    private String name;
    private Integer age;

    public String getName() {
        return name;
    }

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

    public Integer getAge() {
        return age;
    }

    public void setAge(Integer age) {
        this.age = age;
    }

    public Person(String name, Integer age) {
        this.name = name;
        this.age = age;
    }

    @Override
    public String toString() {
        return "Person{" +
                "name='" + name + '\'' +
                ", age=" + age +
                '}';
    }

    @Override
    public int compareTo(Object o) {
        int flag=1;
        if(o instanceof Person) {
            Person p=(Person)o;
            flag=this.age-p.age;
            if(flag==0){
                flag=this.name.compareTo(p.name);
            }
        }
        return flag;
    }
}
public class CompareToTest1 {
    public static void main(String[] args) {
        Person p=new Person("Abi",8);
        Person p1=new Person("Jinx",9);
        System.out.println( p.compareTo(p1));
    }
}

TreeSet的特色:

1.元素惟一性

2.可自定義排序的(所存儲的對象必須實現Comparable接口覆寫compareTo方法)

3.不容許null存在(每次添加都會做比較的)

4.不是線程安全

基於 TreeMapNavigableSet 實現。使用元素的天然順序對元素進行排序,或者根據建立 set 時提供的 Comparator 進行排序,具體取決於使用的構造方法。

此實現爲基本操做(addremovecontains)提供受保證的 log(n) 時間開銷。

注意,若是要正確實現 Set 接口,則 set 維護的順序(不管是否提供了顯式比較器)必須與 equals 一致。(關於與 equals 一致 的精肯定義,請參閱 ComparableComparator。)這是由於 Set 接口是按照 equals 操做定義的,但 TreeSet 實例使用它的 compareTo(或 compare)方法對全部元素進行比較,所以從 set 的觀點來看,此方法認爲相等的兩個元素就是相等的。即便 set 的順序與 equals 不一致,其行爲也 定義良好的;它只是違背了 Set 接口的常規協定。

public class Student extends Person {

    public Student(String name, Integer age) {
        super(name, age);
    }
    private Integer stuNo;

    public Integer getStuNo() {
        return stuNo;
    }

    public void setStuNo(Integer stuNo) {
        this.stuNo = stuNo;
    }

    public Student(String name, Integer age, Integer stuNo) {
        super(name, age);
        this.stuNo = stuNo;
    }

    @Override
    public String toString() {
        return "Student{" +
                super.toString()+
                "stuNo=" + stuNo +
                '}';
    }
}
import java.util.Set;
import java.util.TreeSet;

public class TreeSetTest {
    public static void main(String[] args) {
        Person p=new Person("Abi",8);
        Person p1=new Person("Jinx",10);
        Student s=new Student("Mia",9,2);
        Set<Person> set= new TreeSet<>();
        set.add(p);
        set.add(p1);
        set.add(s);
        System.out.println(set);
    }
}

75.可變參數

可變參數定義的語法:數據類型...變量名

能夠表明數組或者單個數的傳遞

可變參數方法的語法:

修飾符 返回值類型 方法名(數據類型...變量名){

}

若是調用的時候發現有正好能夠匹配的方法就不會調用可變參數方法,若是調用方法的時候不存在正好匹配的方法則調用可變參數方法

public class DynamicParam {
    public int add(int...a){
        int s=0;
        for (int i = 0; i < a.length; i++) {
            s+=a[i];
        }
        return s;
    }
}
public class DynamicParamTest {
    public static void main(String[] args) {
        DynamicParam d=new DynamicParam();
        int s=d.add(12);
        int s1=d.add(12,13,15,100);
        int s2=d.add(new int[]{12,13,15,100});
        System.out.println(s);
        System.out.println(s1);
        System.out.println(s2);
    }
}

76.數組工具類Arrays

import java.util.Arrays;

public class ArraysTest {
    public static void main(String[] args) {
        int[] i={1,2,3,4,5,6};
        String s= Arrays.toString(i);
        System.out.println(s);
        Person[] p = new Person[2];
        p[0]=new Person("aa",3);
        p[1]=new Person("bb",4);
        String s1=Arrays.toString(p);
        System.out.println(s1);
    }
}

import java.util.Arrays;

public class ArraysTest1 {
    public static void main(String[] args) {
        Person[] p = new Person[4];
        //注意:對數組中的對象排序,數組中的對象必須實現Comparable接口
        p[0]=new Person("aa",3);
        p[1]=new Person("bb",5);
        p[2]=new Person("cc",1);
        p[3]=new Person("dd",4);
        Arrays.sort(p);
        System.out.println(Arrays.toString(p));
    }
}

注意不能把基本數據類型的數組轉換成集合,若是傳遞了基本數據類型的集合,就會把數組的類型做爲泛型,能夠是包裝類的數組,數組轉換成的集合長度不可改變

import java.util.Arrays;
import java.util.List;

public class ArraysTest2 {
    public static void main(String[] args) {
        Integer[] i={1,2,3,4,5,6};
        List<Integer> integers = Arrays.asList(i);
        System.out.println(integers);
        //數組轉換成集合的長度不可變UnsupportedOperationException
        //list.add(9);
    }
}

77.集合工具類Collections

面試題:Collection是集合的接口;Collections是集合的工具類

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

public class CollectionsTest {
    public static void main(String[] args) {
        List<Person> list = new ArrayList<>();
        list.add(new Person("Bob",12));
        list.add(new Person("Vob",8));
        list.add(new Person("Sob",13));
        list.add(new Person("Bob",5));
        System.out.println("--------集合倒置---------");
        Collections.reverse(list);
        System.out.println(list);
        System.out.println("--------集合順序打亂---------");
        Collections.shuffle(list);
        System.out.println(list);
        System.out.println("--------集合排序---------");
        //能夠排序的泛型的類必須實現Comparable接口或者使用外置的比較器
        Collections.sort(list);
        System.out.println(list);
        //Collection中只有Vector是線程安全的
        Collections.synchronizedList(list);
    }
}

public class ComparatorDemo implements Comparator<People> {
    @Override
    public int compare(People o1, People o2) {
        int flag=o1.getAge()-o2.getAge();
        if(flag==0){
            flag=o1.getName().compareTo(o2.getName());
        }
        return flag;
    }
}
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

public class CollectionsTest1 {
    public static void main(String[] args) {
        List<People> list = new ArrayList<>();
        list.add(new People("Bob", 12));
        list.add(new People("Vob", 8));
        list.add(new People("Sob", 13));
        list.add(new People("Bob", 5));
        //根據指定比較器產生的順序對指定列表進行排序。sort(List<T> list, Comparator<? super T> c) 
        Collections.sort(list,new ComparatorDemo());
        System.out.println(list);
    }
}

相關文章
相關標籤/搜索