Java基礎集合篇02-數據結構、List和Set集合

1. 數據結構基礎篇

1.1 什麼是數據結構 ?

 

 

 
數據結構

​ 數據結構就是計算機存儲、組織數據的方式 。前端

​ 指的是相互之間存在着特定關係的一種或多種的數據元素集合。java

1.2 爲何要學習數據結構?

​ 一般狀況下,精心選擇合適的數據結構能夠帶來更高的運行或存儲的效率。程序員

​ 數據結構每每同高效的檢索算法和索引技術有關。算法

1.3 數據結構-棧

  • 棧:棧(stack)又名堆棧,是一種運算受限的線性表。後端

  • 受限:限定僅在表尾進行插入和刪除操做的線性表(這一端被稱爲棧頂,另外一端稱爲棧底)。數組

     
    棧底和棧頂

     

  • 特性: 先進後出。數據結構

    • 進棧(壓棧):以下圖ide

       
      出棧入棧

       

    • 出棧(彈棧):以下圖工具

       
      出棧和入棧

       

1.4 數據結構-隊列

  • 隊列:是一種受限的特殊線性表。
  • 受限:只容許在表的前端(隊頭)進行刪除操做,後端(隊尾)進行插入操做。
  • 特性:先進先出
     
    隊列

1.5 數據結構-數組

  • 數組:一組有序的(索引有序而且從0開始)類型相同的元素集合。
  • 特性:有序、同類型、長度固定。
  • 應用效果:
    • 查詢快。
      • 從數組索引0開始查找,根據指定位置的偏移量可快速獲取數據。
    • 增刪慢。
      • 數組的長度是固定的,若刪除或增長一格元素,則會先建立一個新的數據,再把原數組的數據根據操做複製到新數組中。

1.6 數據結構-鏈表(單鏈表)

 
鏈表
  • 鏈表:是一種物理存儲單元上非連續、非順序的存儲結構,數據元素的邏輯順序是經過鏈表中的指針連接次序實現的。
  • 特色:
    • 由一系列結點(鏈表中的每個元素稱爲結點)組成。
    • 結點能夠在運行時動態生成。
    • 每一個結點包括兩個部分
      • 一個是存儲數據元素的數據域
      • 另外一個是存儲下一個結點地址的指針域。
  • 應用效果:
    • 查詢慢:鏈表的地址不是連續的,每次查找都得從頭開始查找。
    • 增刪快:增刪操做不會影響鏈表的總體結構。

1.7 數據結構-紅黑樹

 
紅黑樹
  • 紅黑樹(對稱二叉B樹):一種自平衡二叉查找樹。
  • 應用效果:
    • 查詢速度快。
      • 在進行插入和刪除操做時經過特定操做保持二叉查找樹的平衡,從而得到較高的查找性能

2. List集合

2.1 List集合介紹

​ List做爲Collection集合的子接口,不但繼承了Collection接口中的所有方法,並且還增長了一些根據元素索引來操 做集合的特有方法,以下:性能

  • 方法:

    public void add(int index, E element) : 將指定的元素,添加到該集合中的指定位置上。

    public E get(int index) :返回集合中指定位置的元素。

    public E remove(int index) : 移除列表中指定位置的元素, 返回的是被移除的元素。

    public E set(int index, E element) :用指定元素替換集合中指定位置的元素,返回值的更新前的元素

  • 代碼:

    List list = new ArrayList(); list.add("a"); list.add("b"); list.add("c"); // public void add(int index, E element) : 將指定的元素,添加到該集合中的指定位置上。 list.add(1,"d"); System.out.println(list); // [a, d, b, c] // public E get(int index) :返回集合中指定位置的元素。 System.out.println(list.get(2)); // b // public E remove(int index) : 移除列表中指定位置的元素, 返回的是被移除的元素。 list.remove(1); System.out.println(list); // [a, b, c] // public E set(int index, E element) :用指定元素替換集合中指定位置的元素,返回值的更新前的元素 list.set(1,"B"); System.out.println(list); // [a, B, c]
  • 特色:

    • 存取順序一致,而且有索引。
    • 元素內容可重複。

2.2 List集合實現類-ArrayList

​ java.util.ArrayList 集合數據存儲的結構是數組結構。元素增刪慢,查找快,用於平常開發中使用最多的功能爲 查詢數據、遍歷數據,因此 ArrayList 是最經常使用的集合。

​ 許多程序員開發時很是隨意地使用ArrayList完成任何需求,並不嚴謹,這種用法是不提倡的。

2.3 List集合實現類-LinkedList

  • 介紹:java.util.LinkedList 集合數據存儲的結構是鏈表結構。方便元素添加、刪除的集合。

    LinkedList是一個雙向鏈表,那麼雙向鏈表是什麼樣子的呢,如圖


     
    鏈表
  • 經常使用方法

    • 方法:

      實際開發中對一個集合元素的添加與刪除常常涉及到首尾操做,而LinkedList提供了大量首尾操做的方法。

      public void addFirst(E e) :將指定元素插入此列表的開頭。

      public void addLast(E e) :將指定元素添加到此列表的結尾。

      public E getFirst() :返回此列表的第一個元素。

      public E getLast() :返回此列表的最後一個元素。

      public E removeFirst() :移除並返回此列表的第一個元素。

      public E removeLast() :移除並返回此列表的最後一個元素。

      public E pop() :今後列表所表示的堆棧處彈出一個元素。

      public void push(E e) :將元素推入此列表所表示的堆棧。

      public boolean isEmpty() :若是列表不包含元素,則返回true。

    • 代碼:

      LinkedList list = new LinkedList(); list.add("a"); list.add("b"); // public void addFirst(E e) :將指定元素插入此列表的開頭。 list.addFirst("A"); // public void addLast(E e) :將指定元素添加到此列表的結尾。 list.addLast("B"); System.out.println(list); // [A, a, b, B] // public E getFirst() :返回此列表的第一個元素。 System.out.println(list.getFirst()); // A // public E getLast() :返回此列表的最後一個元素。 System.out.println(list.getLast()); // B // public E removeFirst() :移除並返回此列表的第一個元素。 list.removeFirst(); // public E removeLast() :移除並返回此列表的最後一個元素。 list.removeLast(); System.out.println(list); //[a, b] // public E pop() :今後列表所表示的堆棧處彈出一個元素。 list.pop(); System.out.println(list); // [b] // public void push(E e) :將元素推入此列表所表示的堆棧。 list.push("a"); System.out.println(list); // [a, b] // public boolean isEmpty() :若是列表不包含元素,則返回true。 System.out.println(list.isEmpty()); // false

3. Set集合

3.1 Set集合介紹

  • 繼承了Collectin集合
  • 沒有擴充方法
  • 與List集合不一樣的是會保證集合中元素的惟一性。

3.2 Set集合實現類-HashSet

  • HashSet介紹

    • 集合中的元素存取是無序的

    • 集合中的元素是不重複的

    • HashSet 是根據對象的哈希值來肯定元素在集合中的存儲位置,所以具備良好的存取和查找性能。保證元素惟一性的方式依賴於: hashCode 與 equals 方法。

    • 代碼:

      Set set = new HashSet(); set.add("張三"); set.add("李四"); set.add("李四"); set.add("王五"); set.add("趙六"); System.out.println(set); // [李四, 張三, 王五, 趙六]
  • 哈希值

    • 一個十進制的邏輯地址。

    • 全部的對象都繼承裏Object中的HashCode方法

    • 代碼:

      System.out.println("a".hashCode()); // 97 System.out.println("b".hashCode()); // 98 System.out.println("張三".hashCode()); // 774889 System.out.println("李四".hashCode()); // 842061 int[]arr1={1,2,3}; System.out.println(arr1.hashCode()); //1355531311
  • HashSet存儲數據的結構

    • 結構:數組+鏈表/紅黑樹

      ​ 在JDK1.8以前,哈希表底層採用數組+鏈表實現,即便用鏈表處理衝突,同一hash值的鏈表都存儲在一個鏈表裏。

      ​ 可是當位於一個桶中的元素較多,即hash值相等的元素較多時,經過key值依次查找的效率較低。而JDK1.8中,哈希表存儲採用數組+鏈表+紅黑樹實現,當鏈表長度超過閾值(8)時,將鏈表轉換爲紅黑樹,這樣大大減小了查找 時間。

    • 圖解存儲結構

       
      Set

       

  • 圖解元素惟一性原理流程圖
     
    流程圖
  • 小結:

    總而言之,JDK1.8引入紅黑樹大程度優化了HashMap的性能,那麼對於咱們來說保證HashSet集合元素的惟一, 其實就是根據對象的hashCode和equals方法來決定的。若是咱們往集合中存放自定義的對象,那麼保證其惟一, 就必須複寫hashCode和equals方法創建屬於當前對象的比較方式。

  • HashSet存儲自定義類型對象

    • 要求:自定義人物類型(含有姓名、年齡),用HashSet集合存儲,若對象的姓名和年齡一致則在集合中不容許重複

    • 代碼:

      /*人物類*/ public class People { private String name; private int age; public People(String name, int age) { this.name = name; this.age = age; } @Override public boolean equals(Object o) { if (this == o) return true; if (o == null || getClass() != o.getClass()) return false; People people = (People) o; return age == people.age && name.equals(people.name); } @Override public int hashCode() { return Objects.hash(name, age); } public String getName() { return name; } public void setName(String name) { this.name = name; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } } // 入口類 public class Main { public static void main(String[] args) { People p1 = new People("張三",10); People p2 = new People("李四",12); People p4 = new People("李四",12); People p3 = new People("王五",10); HashSet set = new HashSet(); set.add(p1); set.add(p2); set.add(p3); set.add(p4); System.out.println(set.size()); // 3 } }

3.3 Set集合實現類-LinkedHashSet

  • 組織結構:哈希表(數組+鏈表/紅黑樹) + 鏈表(記錄存取順序)

  • 特色:

    • 元素惟一性
    • 元素存取有序。
  • 代碼:

    LinkedHashSet set = new LinkedHashSet(); set.add("張三"); set.add("李四"); set.add("李四"); set.add("王五"); set.add("趙六"); System.out.println(set); // [張三, 李四, 王五, 趙六]

3.4 其餘擴展-可變參數

  • 格式:

    修飾符 返回值類型 方法名(參數類型... 形參名){ } 等價於 修飾符 返回值類型 方法名(參數類型[]形參名){ }
  • 代碼:

    public static void main(String[] args) { System.out.println(add(1,2,3)); // 6 System.out.println(add(1,200,300,400)); // 901 } public static int add(int...num) { int sum = 0; for (int i = 0; i < num.length; i++) { sum += num[i]; } return sum; }
  • 原理:在編譯成class文件時,源代碼中的可變參數會自動變成數組。

  • 注意事項:

    • 可變參數類型要一致
    • 可變參數要放在參數列表最後

4. Collections

4.1 Collection介紹和使用

​ java.utils.Collections 是集合工具類,用來對集合進行操做 。經常使用的方法以下:

  • 方法:

    public static <T> boolean **addAll(Collection<T> c, T... elements)** :往集合中添加一些元素。

    public static void **shuffle(List<?> list)** 打亂順序 :打亂集合順序。

    public static <T> void **sort(List<T> list)** :將集合中元素按照默認規則排序。

    public static <T> void **sort(List<T> list,Comparator<? super T> )** :將集合中元素按照指定規則排序。

  • 代碼:

    ArrayList<Integer> list = new ArrayList<>(); //public static <T> boolean addAll(Collection<T> c, T... elements) :往集合中添加一些元素。 Collections.addAll(list, 1, 3, 4, 5, 6, 8, 7); System.out.println(list); // [1, 3, 4, 5, 6, 8, 7] //public static void shuffle(List<?> list) 打亂順序 :打亂集合順序。 Collections.shuffle(list); System.out.println(list); // 隨機順序[5, 4, 6, 3, 7, 1, 8] //public static <T> void sort(List<T> list) :將集合中元素按照默認規則排序。 Collections.sort(list); System.out.println(list); // 默認升序[1, 3, 4, 5, 6, 7, 8] //public static <T> void sort(List<T> list,Comparator<? super T> ) :將集合中元素按照指定規則排序。 Collections.sort(list, new Comparator<Integer>() { @Override public int compare(Integer o1, Integer o2) { return o2-o1; } }); System.out.println(list);
  • 注意事項:

    • 若要對自定義對象進行排序時,使用 sort(List<T> list)時,自定義類型須要實現Comparable接口,而且要從新CompareTo方法

    • 代碼:

      public class People implements Comparable<People> { private String name; private int age; public People(String name, int age) { this.name = name; this.age = age; } public String getName() { return name; } public void setName(String name) { this.name = name; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } @Override public int compareTo(People o) { return this.age - o.age; // 升序 // return o.age-this.age; 降序 } }
相關文章
相關標籤/搜索