1. 程式人生 > 其它 >JAVA集合基礎03---List集合,資料結構,Set集合雜湊值,排序器

JAVA集合基礎03---List集合,資料結構,Set集合雜湊值,排序器

JAVA集合基礎03

List集合概述和特點

  • 需要導包,繼承Collection

  • 有序集合(也成為序列),使用者可以精確控制列表中每個元素的插入位置,使用者可以通過整數索引訪問元素,並搜尋列表中的元素

  • 與set集合不同,列表通常允許重複的元素

  • 有序:儲存和取出的元素順序一致

  • 可重複:儲存的元素可重複

  • 和Collection集合的區別是List集合有索引

public static void main(String[] args) {
    //建立集合物件
    List<String> list = new ArrayList<String>();

    //建立物件
    list.add("AAAAA");
    list.add("BBBBB");
    list.add("CCCCC");
    list.add("CCCCC");

    //輸出集合物件
    System.out.println(list);

    //迭代器的方式遍歷
    Iterator<String> it = list.iterator();
    while(it.hasNext()){
        String s = it.next();
        System.out.println(s);
    }
}

List集合的特有方法

  • 父類Collection沒有,子類ArrayList擁有

遍歷List集合有兩種方式

  • 遍歷器方式
  • 傳統的增強For迴圈

併發修改異常

  • ConcurrentModificationException:當不允許這樣的修改時,可以通過檢測物件的併發修改的方法來丟擲此異常

  • 假設前面呼叫了3次add,所以實際修改集合次數modcount=3,然後開始迭代器iterator,預期修改集合次數expectcount就被賦值為3,迭代器執行過程中,採用Next()方法遍歷同時(判斷集合裡面有沒有"world"這個元素,如果有,就新增一個"javaee"元素)的條件實現,if又使用了add的方法,從而導致modcount++,但expect不被重新賦值保持3,Next()方法自身會執行兩種修改方法的值是否相等的判斷,最終導致modcount!=expectcount丟擲了併發修改異常

  • 使用For迴圈,get()方法的遍歷則不會對兩種修改次數種類的值進行是否相等進行判斷所以並不會丟擲併發異常可以正常執行

List迭代器

ListIterator:列表迭代器

  • 通過List集合的ListIterator()方法得到,所以說它是List集合特有的迭代器

  • 通過允許程式設計師沿任一方向遍歷列表的列表迭代器,在迭代期間修改列表,並獲取列表中迭代器打的當前位置

  • E next() :返回迭代中下一個元素

  • boolean hasNext(): 如果迭代具有更多元素,則返回true

  • E previous():返回列表中的上一個元素

  • boolean hasPrevious():如果在相反方向遍歷列表時有更多元素,則返回true

  • void add(E e):將指定的元素插入列表

  • 列表List迭代器不會出現併發修改異常

增強For迴圈

  • 簡化陣列和Collection集合的遍歷

  • 實現Iterable介面的類允許其物件成為增強型for語句的目標

  • 格式

    • for(元素資料型別 變數名:陣列或者Collection集合){

      //在此處使用變數即可,該變數就是元素

      }

  • 內部原理是一個Iterator迭代器

資料結構

棧和佇列

  • 資料結構是計算機儲存,組織資料的方式,是指在相互之間存在一種或多種特定關係的資料元素的集合

  • 精心選擇的資料結構可以帶來更高的執行或者儲存效率

  • 資料進入棧模型的過程稱為:壓/進棧

  • 資料離開棧模型的過程稱為:彈/出棧

  • 棧是先進後出的一種資料模型

佇列

  • 資料從後端進入佇列模型的過程稱為:入佇列
  • 資料從前端進入佇列模型的過程稱為:出佇列
  • 佇列是先進先出的一種資料模型

常見資料結構之陣列

  • 查詢資料通過索引定位,查詢任意資料耗時相同,查詢效率高
  • 刪除資料時,要將原始資料刪除,同時後面的每個資料前移,刪除效率低
  • 新增資料時,新增位置後的每個資料後移,再新增元素,新增效率極低
  • 陣列是一種查詢快,增刪慢的模型

常見資料結構之連結串列

  • 節點的儲存位置(地址),儲存具體的資料
  • 節點當中還存在下一個節點的位置
  • “^”表示結點指向空地址
  • 尾插法,尾部的地址替換
  • 連結串列是一種增刪快,查詢慢的模型(對比陣列
  • 查詢某一個數據是否存在,必須要從頭開始

List集合子類的特點

List集合常用子類:ArrayList,LinkedList

  • ArrayList:底層資料結構是陣列,查詢快,增刪滿
  • LinkedList:底層資料結構是連結串列,查詢慢,增刪快

Set集合概述和特點

  • 不包含重複元素的集合
  • 沒有帶索引的方法,所以不能使用普通for迴圈遍歷
  • 實現類HashSet:對集合的順序不作任何保證

雜湊值

  • 是JDK根據物件的地址或者字串或者數字算出來的int型別的數值

  • Object類中有一個方法可以獲取物件的雜湊值

    • public int hashCode()
      
    • 返回物件的雜湊碼值

    • 同一個物件多次呼叫hashCode()方法的雜湊值是相同的

    • 預設情況下不同物件的雜湊值是不一樣的,通過方法重寫可以實現不同物件的雜湊值是相同的

HashSet集合概述和特點

  • 底層資料結構是雜湊表
  • 對集合的迭代順序不做任何保證,也就是說不保證儲存和取出的元素順序一致
  • 沒有帶索引的方法,所以不能使用普通for迴圈遍歷
  • 由於是set集合,所以不包含重複元素的集合

HashSet集合保證元素唯一性原始碼分析

  • 要保證元素唯一性,需要重寫hasCode()和equals()

  • 雜湊值是為了解決遍歷時間消耗大而設計出來的

  • hashcode值就相當於門牌號,然後房間裡分配的空間就是來儲存元素的

常見資料結構之雜湊表

雜湊表

  • JDK8之前,底層採用陣列+連結串列實現,可以說是一個元素為連結串列的陣列
  • JDK8後,在長度比較長的時候,底層實現了優化

LinkedHashSet集合概述和特點

  • LinkedHashSet集合特點
    • 雜湊表和連結串列實現的Set介面,具有可預測的迭代次序
    • 由連結串列保證元素有序,也就是說元素的儲存和取出順序是一致的
    • 有雜湊表保證元素唯一,也就是說沒有重複的元素

TreeSet集合概述和特點

  • 間接實現Set介面,實現Set介面的子類

TreeSet集合特點

  • 元素有序,這裡的順序不是指儲存和取出的順序,而是按照一定的規則進行排序,具體排序方式取決於構造方法

    • TreeSet():根據其元素的自然排序進行排序
    • TreeSet(Comparator comparator):根據指定的比較器進行排序
  • 由於沒有帶索引的方法,所以不能用普通For迴圈遍歷

  • 由於是Set集合,所以不包含重複元素的集合

  • 集合只能使用引用型別,或者基本型別的包裝型別

自然排序Comparable的使用

  • 使用TreeSet無參構造後,對物件類(如Student)進行增加介面Comparable

  • 增加介面後,對介面的compareTo方法進行重寫

  • return 0;則輸出第一個,return 1;則是按照物件輸入順序從先到後遍歷,-1則是反過來

  • 想要按照輸入Student的年齡從小到大

    • int num = this.age - s.age
      
    • this是誰呼叫它就是誰,this理解為接下來要儲存的元素,s理解為集合裡已經儲存的元素(比如儲存s2時s2就是現在要儲存的元素,s1相對就是已經有的元素),相減為正數,則從小到大依次排序,想要升序,this在前面,想要降序this放在後面

    • 需要相同年齡不同物件也要遍歷的話

    • int num2 = num == 0?this.name.compareTo(s.name):num
       return num2
      
    • 1.首先考慮字元首字母,按照A—Z排序,如果首字母相同再看下一位字母,以此類推

    • 2.若字母相同,例如Student和Students比較,已有的字母相同,那麼會繼續比較字串的長度,短的排前面

    • 3.這裡CamparaTo方法返回值在1和2中分別是返回兩個字母的Unicode差值和返回字串長度的差值,即length的差,都是int型別的返回值

結論

  • 用TreeSet集合儲存自定義物件,無參構造方法使用的是自然排序對元素進行排序的
  • 自然排序,就是讓元素所屬的類實現Comparable介面,重寫compareTo方法
  • 重寫方法時,一定要注意排序規則必須按照要求的主要條件和次要條件來寫

比較器排序Comparator的使用

public static void main(String[] args) {
    TreeSet<Students> tr = new TreeSet<>(new Comparator<Students>() {//匿名內部類
        @Override
        public int compare(Students s1, Students s2) {
            //由於是在Demo類中重寫,按照之前的重寫方法,this所指的物件則是Demo
            //因此傳入兩個引數,不使用this即可
            int num = s1.getAge() - s2.getAge();
            int num2 = num == 0 ? s1.getName().compareTo(s2.getName()) : num;
            return num2;
        }
    });
    Students s1 = new Students("xuzhiyuan", 25);
    Students s2 = new Students("zhoujielun", 29);
    Students s3 = new Students("pengyuyan", 21);
    Students s4 = new Students("honghuihuang", 24);
    Students s5 = new Students("xuxian", 24);

    tr.add(s1);
    tr.add(s2);
    tr.add(s3);
    tr.add(s4);
    tr.add(s5);

    for (Students s : tr) {
        System.out.println(s.getName() + "," + s.getAge());
    }


}
  • 使用TreeSet集合儲存自定義物件,帶參構造方法使用的是比較器排序對元素進行排序
  • Comparator預設從小到大排列,前一個數減去後一個數,大於0調換位置,否則不變
  • 比較器排序就是讓集合構造方法接收Comparator的實現類物件,重寫compare(To1,To2)方法
  • 重寫方法時,一定要注意排序規則必須按照要求的主要條件和次要條件來寫