java複習第4天---4.1---集合---數據結構和集合框架結構

java複習第4天---4.1---集合---數據結構和集合框架結構


目錄




內容

1、數據結構

  程序 = 數據 + 算法 。其中數據設計數據類型及數據的組織存儲,既數據結構。這裏只簡單介紹下常用的數據結構,詳細可以自行查閱

1.1、 數組

  內存空間中分配的連續的空間地址

  • 特點:有序可重複,通過數組下標訪問對應的元素

  • 優點:

    • 查詢效率高
    • 數組遍歷快
  • 缺點

    • 數組大小固定後,無法擴容
    • 增刪效率低:底層通過System.arrayCopy實現數組複製實現增減
    • 只能存儲同一種類型的數據元素
  • 示例:

      int[] arr = {1, 3, 5 ,7};
      查看第二個元素:arr[1]
    

1.2、 鏈表

  • 簡介:鏈表是物理存儲單元上非連續的、非順序的存儲結構,數據元素的邏輯順序是通過鏈表的指針地址實現,每個元素包含兩個結點,一個是存儲元素的數據域 (內存空間),另一個是指向下一個結點地址的指針域。根據指針的指向,鏈表能形成不同的結構,例如單鏈表,雙向鏈表,循環鏈表等。
  • 特點:有序可重複,通過鏈表指針移動訪問對應的元素
  • 優點:
    • 增刪效率高:只需要改變前後元素的指針指向
  • 缺點:
    • 查詢效率低:地址非連續,通過存儲的地址值,移動指針查找元素

1.3、 棧

  • 簡介:棧是一種特殊的線性表,僅能在線性表的一端操作,棧頂允許操作,棧底不允許操作。
  • 特點:先進後出,或者說是後進先出,從棧頂放入元素的操作叫入棧,取出元素叫出棧。
  • 適用場景:實現遞歸功能方面的場景,例如斐波那契數列
  • 圖示1.3-1:在這裏插入圖片描述

1.4、隊列

  • 簡介:棧也是一種特殊的線性表,需要在線性表的二端操作,一端寫入,一端讀出。
  • 特點:先進先出
  • 使用場景:在多線程阻塞隊列管理中非常適用。
    +圖示1.4-1:[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-OM0RfiXE-1590322493508)(./images/queue.png)]

1.5、樹

  • 簡介:樹是一種數據結構,它是由n(n>=1)個有限節點組成一個具有層次關係的集合。把它叫做 “樹” 是因爲它看起來像一棵倒掛的樹,也就是說它是根朝上,而葉朝下的。它具有以下的特點:
  • 特點
    • 每個節點有零個或多個子節點;
    • 沒有父節點的節點稱爲根節點;
    • 每一個非根節點有且只有一個父節點;
    • 除了根節點外,每個子節點可以分爲多個不相交的子樹;

  在日常的應用中,我們討論和用的更多的是樹的其中一種結構,就是二叉樹。
[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-MtQZCe42-1590322493509)(./images/binary-tree.png)]
二叉樹是樹的特殊一種,具有如下特點:

  1. 每個結點最多有兩顆子樹,結點的度最大爲2。
  2. 左子樹和右子樹是有順序的,次序不能顛倒。
  3. 即使某結點只有一個子樹,也要區分左右子樹。

  二叉樹是一種比較有用的折中方案,它添加,刪除元素都很快,並且在查找方面也有很多的算法優化,所以,二叉樹既有鏈表的好處,也有數組的好處,是兩者的優化方案,在處理大批量的動態數據方面非常有用。

  • 擴展:
    二叉樹有很多擴展的數據結構,包括平衡二叉樹、紅黑樹、B+樹等,這些數據結構二叉樹的基礎上衍生了很多的功能,在實際應用中廣泛用到,例如mysql的數據庫索引結構用的就是B+樹,還有HashMap的底層源碼中用到了紅黑樹。這些二叉樹的功能強大,但算法上比較複雜,想學習的話還是需要花時間去深入的。

1.6、 散列表

  • 簡介:散列表,也叫哈希表,是根據關鍵碼和值 (key和value) 直接進行訪問的數據結構,通過key和value來映射到集合中的一個位置,這樣就可以很快找到集合中的對應元素。

  • 算法:
    記錄的存儲位置=f(key)
    這裏的對應關係 f 稱爲散列函數,又稱爲哈希 (hash函數),而散列表就是把Key通過一個固定的算法函數既所謂的哈希函數轉換成一個整型數字,然後就將該數字對數組長度進行取餘,取餘結果就當作數組的下標,將value存儲在以該數字爲下標的數組空間裏,這種存儲空間可以充分利用數組的查找優勢來查找元素,所以查找的速度很快。

  • JDK1.8前後存儲變化

    • JDK1.8之前:[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-q5UhM6Zm-1590322493511)(./images/hash.png)]

    • JDK1.8之後:[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-MRWaU6hH-1590322493512)(./images/hash-jdk1_1.8-after.png)]

    • 解析:從圖中可以看出,左邊很明顯是個數組,數組的每個成員包括一個指針,指向一個鏈表的頭,當然這個鏈表可能爲空,也可能元素很多。我們根據元素的一些特徵把元素分配到不同的鏈表中去,也是根據這些特徵,找到正確的鏈表,再從鏈表中找出這個元素。

  • 應用:

    • 哈希表在應用中也是比較常見的,就如Java中有些集合類就是借鑑了哈希原理構造的,例如HashMap,HashTable等,利用hash表的優勢,對於集合的查找元素時非常方便的,然而,因爲哈希表是基於數組衍生的數據結構,在添加刪除元素方面是比較慢的,所以很多時候需要用到一種數組鏈表來做,也就是拉鍊法。拉鍊法是數組結合鏈表的一種結構,較早前的hashMap底層的存儲就是採用這種結構,直到jdk1.8之後才換成了數組加紅黑樹的結構,其示例圖如上:
    • 哈希表的應用場景很多,當然也有很多問題要考慮,比如哈希衝突的問題,如果處理的不好會浪費大量的時間,導致應用崩潰。

1.7、 堆

  堆是一種比較特殊的數據結構,可以被看做一棵樹的數組對象,具有以下的性質:

  • 堆中某個節點的值總是不大於或不小於其父節點的值;

  • 堆總是一棵完全二叉樹。

   將根節點最大的堆叫做最大堆或大根堆,根節點最小的堆叫做最小堆或小根堆。常見的堆有二叉堆、斐波那契堆等。

堆的定義如下:

n個元素的序列{k1,k2,ki,…,kn}當且僅當滿足下關係時,稱之爲堆。(ki <= k2i,ki <= k2i+1)或者(ki >= k2i,ki >= k2i+1), (i = 1,2,3,4…n/2),滿足前者的表達式的成爲小頂堆,滿足後者表達式的爲大頂堆,這兩者的結構圖可以用完全二叉樹排列出來,示例圖如下:

[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-6uCOGBEv-1590322493514)(./images/heap1.png)]

  • 適用場景:因爲堆有序的特點,一般用來做數組中的排序,稱爲堆排序。

1.8、 圖

  圖是由結點的有窮集合V和邊的集合E組成。其中,爲了與樹形結構加以區別,在圖結構中常常將結點稱爲頂點,邊是頂點的有序偶對,若兩個頂點之間存在一條邊,就表示這兩個頂點具有相鄰關係。

  按照頂點指向的方向可分爲無向圖和有向圖:

[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-ijqlDhp2-1590322493515)(./images/undigraph.png)][外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-272MZAXY-1590322493516)(./images/digraph.png)]
在這裏插入圖片描述
  圖是一種比較複雜的數據結構,在存儲數據上有着比較複雜和高效的算法,分別有鄰接矩陣 、鄰接表、十字鏈表、鄰接多重表、邊集數組等存儲結構,這裏不做展開,讀者有興趣可以自己學習深入。

2、集合框架

  Java中的集合包含多種數據結構,如鏈表、隊列、哈希表等。從類的繼承結構來說,可以分爲兩大類,一類是繼承自Collection接口,這類集合包含List、Set和Queue等集合類。另一類是繼承自Map接口,這主要包含了哈希表相關的集合類。下面我們看一下這兩大類的繼承結構圖:

2.1、 Collection接口

[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-U7RNs3K2-1590322493517)(./images/collection_2.png)]
圖中的綠色的虛線代表實現,綠色實線代表接口之間的繼承,藍色實線代表類之間的繼承。

2.1.1、List

  列表接口,元素有序,可重複。常用實現類ArrayList和LinkedList.

  • ArrayList:底層實現爲數組,查詢效率高,增刪慢
  • LinkedList:底層實現爲鏈表,增刪快,查詢慢

2.1.2、Set

  不包含重複元素的集合。 更正式地,集合不包含一對元素e1和e2 ,使得e1.equals(e2) ,並且最多一個空元素。 正如其名稱所暗示的那樣,這個接口模擬了數學集抽象。常用實現類HashSet,TreeSet.

  • HashSet:底層爲哈希表實現
  • TreeSet:底層樹結構實現,元素經過排序後存儲

2.1.3、Queue

  一般可以直接使用LinkedList完成,從上述類圖也可以看出,LinkedList繼承自Deque,所以LinkedList具有雙端隊列的功能。PriorityQueue的特點是爲每個元素提供一個優先級,優先級高的元素會優先出隊列

2.1.4、Iterable

  從這個圖裏面可以看到Collection類繼承自Iterable,該接口的作用是提供元素遍歷的功能,也就是說所有的集合類(除Map相關的類)都提供元素遍歷的功能。Iterable裏面包含了Iterator的迭代器,其源碼如下,大家如果熟悉迭代器模式的話,應該很容易理解。

public interface Iterator<E> {

boolean hasNext(); // 判斷是否有下一個元素

E next(); // 獲取元素

void remove(); // 移除元素

}

2.2、 Map接口

[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-5UV3DKZg-1590322493518)(./images/map.png)]

   Map類型的集合最大的優點在於其查找效率比較高,理想情況下可以實現O(1)的時間複雜度。Map中最常用的是HashMap,LinkedHashMap與HashMap的區別在於前者能夠保證插入集合的元素順序與輸出順序一致。這兩者與TreeMap的區別在於TreeMap是根據鍵值進行排序的,當然其底層的實現也有本質的區別,如HashMap底層是一個哈希表,而TreeMap的底層數據結構是一棵樹。我們現在看下TreeMap與LinkedHashMap的區別:

package com.paddx.test.collection;

import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.TreeMap;

public class MapTest {
	public static void main(String[] args) {
		Map<String,String> treeMap = new TreeMap<String,String>();
		Map<String,String> linkedMap = new LinkedHashMap<String, String>();

		treeMap.put("b",null);
		treeMap.put("c",null);
		treeMap.put("a",null);

		for (Iterator<String> iter = treeMap.keySet().iterator();iter.hasNext();){
			System.out.println("TreeMap="+iter.next());
		}

		System.out.println("----------分割線---------");

		linkedMap.put("b",null);
		linkedMap.put("c",null);
		linkedMap.put("a",null);

		for (Iterator<String> iter = linkedMap.keySet().iterator();iter.hasNext();){
			System.out.println("LinkedHashMap="+iter.next());
		}
	}
}

運行上述代碼,執行結果如下:

TreeMap=a
TreeMap=b
TreeMap=c
----------分割線---------
LinkedHashMap=b
LinkedHashMap=c
LinkedHashMap=a

  從運行結果可以很明顯的看出這TreeMap和LinkedHashMap的區別,前者是按字符串排序進行輸出的,而後者是根據插入順序進行輸出的。細心的讀者可以發現,HashMap與TreeMap的區別,與之前提到的HashSet與TreeSet的區別是一致的,在後續進行源碼分析的時候,我們可以看到HashSet和TreeSet本質上分別是通過HashMap和TreeMap來實現的,所以它們的區別自然也是相同的。HashTable現在已經很少使用了,與HashMap的主要區別是HashTable是線程安全的,不過由於其效率比較低,所以通常使用HashMap,在多線程環境下,通常用CurrentHashMap來代替。

3、總結

  本文只是從整體上介紹了Java集合框架及其繼承關係。除了上述類,集合還提供Collections和Arrays兩個工具類,此外,集合中排序跟Comparable和Comparator緊密相關。在之後的文章中將對上述提的類在JDK中實現源碼進行詳細分析。

4、參考文章列表

後記

本項目爲參考某馬視頻開發,相關視頻及配套資料可自行度娘或者聯繫本人。上面爲自己編寫的開發文檔,持續更新。歡迎交流,本人QQ:806797785

前端項目源代碼地址:https://gitee.com/gaogzhen/vue-leyou
後端JAVA源代碼地址:https://gitee.com/gaogzhen/JAVA
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章