1. 程式人生 > 實用技巧 >java集合框架:List/Set 介面和其子類

java集合框架:List/Set 介面和其子類

目錄

1. List介面

  • java.util.List介面 extends Collecton介面

  • 特點:

    • 有序的集合
    • 索引,包含了一些帶索引的方法
    • 允許儲存重複的元素
  • 帶索引的方法(特有)(注意防止索引越界異常)

    • public void add(int index ,E element):將元素新增到指定位置。
    • public E get(int index)
      :返回集合中指定位置的元素
    • public E remove (int index):移除列表中指定的元素,返回的是被移除的元素
    • public E set (int index , E element):用指定元素替換集合中指定位置的元素,返回值為更新前的元素。
public class Demo01 {
    public static void main(String[] args) {
        //使用多型建立一個集合物件
        List<String> list = new ArrayList<>();
        list.add("a");
        list.add("b");
        list.add("c");
        list.add("d");
        list.add("a");
        System.out.println(list);//[a, b, c, d, a] 重寫了toString()方法
        // public void add(int index ,E element):將元素新增到指定位置。
        list.add(3,"new3");
        System.out.println(list);//[a, b, c, new3, d, a]

        //remove()
        System.out.println("被移除的元素:"+list.remove(2));//被移除的元素:c
        System.out.println(list);//[a, b, new3, d, a]

        //set()
        System.out.println("被替換的元素:"+list.set(4,"A"));//被替換的元素:a
        System.out.println(list);//[a, b, new3, d, A]

        //遍歷三種方式:
        // 1.普通for迴圈
        for (int i=0;i<list.size();i++){
            System.out.println(list.get(i));
        }
        // 2.使用迭代器
        Iterator<String> it=list.iterator();
        while (it.hasNext()){
            System.out.println(it.next());
        }
        //增強for
        for (String s:list){
            System.out.println(s);
        }
    }
}


2. List的子類

ArrayList

  • java.util.ArrayList集合資料儲存的結構是陣列結構
  • 增刪慢、查詢快
  • 此實現不是同步的

LinkedList集合

  • java.util.LinkedList集合資料儲存的結構是連結串列結構
  • 查詢慢、增刪快
  • 是一個雙向連結串列:有大量對首位操作的方法
  • 使用特有的方法,不能使用多型
  • 此實現不是同步的

Vector

  • Vector底層也是陣列,是同步的,速度慢;
  • 從Java 2平臺v1.2,這個類被改造為實現List介面,可以使用List接口裡的方法
  • 如果不需要執行緒安全的實現,建議使用ArrayList代替Vector


3. Set介面

  • 不包含重複元素的集合
  • 沒有索引,沒有帶索引的方法,不能使用普通的for迴圈遍歷

HashSet

  • 此類實現Set介面,由雜湊表(實際為HashMap例項)支援。
  • 是個無序集合:對集合的迭代順序不作任何保證; 特別是,它不能保證該順序恆久不變。
  • 允許null元素。
  • 此實現不是同步的

雜湊值

  • 是一個十進位制的整數,由系統隨機給出(就是物件的地址,是一個邏輯地址,是模擬出來得到的地址,不是資料實際儲存的實體地址)

  • 在Object類有一個方法,可以獲取物件的雜湊值:int hashCode()

     //hashCode方法的原始碼:
     public native int hashCode();
     //native:代表該方法呼叫的是本地作業系統的方法
     
     //toString方法原始碼:也用了hashCode方法,輸出的邏輯地址是一樣的
     public String toString(){
         return getClass().getName()+"@"+Integer.toHexString(hashCode());
     }
    
  • String類的雜湊值:String類重寫了Object類的hashCode方法

    	String s1=new String("abc");
    	String s2=new String("abc");
    	System.out.println(s1.hashCode());//96354
    	System.out.println(s2.hashCode());//96354
    
  • 兩個元素不同,但是雜湊值相同:雜湊衝突

    	System.out.println("重地".hashCode());//1179395
        System.out.println("通話".hashCode());//1179395
    

HashSet集合儲存資料的結構:雜湊表

  • jdk1.8之前:雜湊表=陣列+連結串列

  • jdk1.8之後:雜湊表=陣列+連結串列;雜湊表=陣列+紅黑樹(提高查詢的速度)

  • 雜湊表的特點:速度快

  • 陣列結構:把元素進行了分組(相同雜湊值的元素是一組),連結串列/紅黑樹結構把相同雜湊值的元素連線到一起

    儲存資料到集合中時:先計算元素的雜湊值

    如果連結串列的長度超過了8位,那麼就會把連結串列轉換為紅黑樹


HashSet儲存自定義型別元素

  • Set集合不允許重複元素的原理

    • Set集合在呼叫add方法時,回撥用元素的hashCode方法和equals方法判斷元素是否重複
  • HashSet存放自定義型別元素時,需要重寫物件中的hashCode()equals()方法,建立自己的比較方式,才能保證HashSet集合中的物件唯一

//例:要求:同名同年齡的人只能儲存一次
public class Person {
    private String name;
    private int age;
    //重寫equals方法
    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;
        Person person = (Person) o;
        return age == person.age &&
                Objects.equals(name, person.name);
    }
    //重寫hashCode方法
    @Override
    public int hashCode() {
        return Objects.hash(name, age);
    }
    public Person(String name, int age) {
        this.name = name;
        this.age = age;
    }

    @Override
    public String toString() {
        return "Person{" +
                "name='" + name + '\'' +
                ", age=" + age +
                '}';
    }
}
//測試類
public class Demo01 {
    public static void main(String[] args) {
      HashSet<Person> set=new HashSet<>();
      Person p1=new Person("aa",20);
      Person p2=new Person("bb",22);
      Person p3=new Person("aa",20);
        System.out.println(p1.hashCode());//97205
        System.out.println(p2.hashCode());//98199
        System.out.println(p3.hashCode());//97205
        System.out.println(p1==p3);//false
        System.out.println(p1.equals(p3));//true
        set.add(p1);
        set.add(p2);
        set.add(p3);
        System.out.println(set);//[Person{name='aa', age=20}, Person{name='bb', age=22}]
    }
}


LinkedHashSet

  • HashSet下有一個子類java.util.LinkedHashSet,是連結串列和雜湊表組合的一個數據儲存結構;
  • 此實現與 HashSet 的不同之外在於,後者維護著一個運行於所有條目的雙重連結列表,多了一條連結串列用來記錄元素的儲存順序,保證元素有序