本篇文章給大家帶來了關于PHP的相關知識,其中主要跟大家介紹數組是怎么靈活支持多數據類型的,感興趣的朋友下面一起來看一下吧,希望對大家有幫助。
在PHP中,數組數據結構的應用處理是使用頻率非常高的,相對于Java、C++ 這種強類型語言來說,PHP的數組簡直可以說是太好用了,可以存儲各種類型的數據(如:數字、字符串甚至對象等),為開發帶來了極大的便利。
基于 PHP 數組的強大特性,我們可以輕易實現更加復雜的數據結構,比如棧、隊列、列表、集合、字典等。
你是否迫不及待的想要一探究竟:PHP到底是如何實現數組的呢?
1、PHP數組底層數據結構
PHP 數組其內部是使用 HashTable 結構來實現的,那就先來簡單說說HashTable吧!
HashTable又稱散列表,是通過key-value的方式來高效地訪問數據的一種結構。哈希表是數組和鏈表的一種合并,集成了數組的尋址快,鏈表的插入快的特點于一身。
HashTable主要分為兩個環節:
1. 哈希函數:哈希函數將要查找的值轉換成數字索引,通過數字索引可以快速的找到值存在的位置。
2. 哈希碰撞:理想情況下,不同的值通過哈希函數后,出來的結果是不一樣的;如果不一樣的值,哈希后出來一樣的數字,我們稱之為哈希碰撞。
因此應用 HashTable 就必須要面臨解決哈希碰撞的問題,主要的解法有兩種:鏈表法,開放尋址法。
在zend_type.h文件中,可以找到 HashTable 的主要結構定義如下:
zend_數組 類型
挑選幾個重點成員介紹一下:
-
gc: 引用計數,垃圾回收使用。
-
arData:散列表中保存存儲元素的數組,其內存是連續的,arData指向數組的起始位置;
-
nTableSize:數組的總容量,即可以容納的元素數,arData 的內存大小就是根據這個值確定的,它的大小的是2的冪次方,最小為8,然后按照 8、16、32…依次遞增;
Bucket 類型
Bucket 的結構比較簡單,主要用來保存元素的 key 和 value,以及一個整型的 h(散列值,或者叫哈希值)。
-
如果元素是數值索引,則其值就是數值索引的值;
-
如果是字符串索引,那么其值就是 key 通過 Time33 算法計算得到的散列值。
h 的值用來最終映射元素的存儲位置。
2、PHP 數組的基本實現
上面部分我們了解了 zend_數組 的數據結構,那接著看看數組的初始化吧:
數組的初始化主要是針對 HashTable 成員的設置,初始化時并不會立即分配 arData 的內存,插入第一個元素之后才會分配 arData 的內存。
為了更好的理解整個hash結構,我們來舉個例子說明一下這個結構:
$data = array( 'hello' => 'haha', 1 => 'me to' 'world' => 'world', 2 => 2 ); unset($data[1]);
那上面的hash結構應該是什么樣的呢?arData存儲的結果應該是什么樣呢?
畫個圖例來看看吧,更直觀一些:
arData是Bucket類型的指針,用來具體存儲每個元素的key,value,按照插入元素的順序存儲數據的,所以數組的順序也是靠這個來保證。
每個arData數組的元素,從圖中可以看到,左邊負數是哈希值取模后的值,存儲的是右邊arData的索引;如-8沖突了,則存儲了鏈表的頭元素。
arData[0]: key='hello',h=xx(具體某個值),val = 'haha'
arData[1]: val是 type=IS_UNDEF 的zval(被unset后,不是立即被刪除,而是置成IS_UNDEF)
arData[2]: key='world',h=xx(具體某個值),val = 'world'
arData[3]: key=NULL,h=2(可能會哈希值沖突),val = 2
….
上面的例子很具體地解釋了nNumUsed,nNumOfElements,arData的意義。
3、PHP 數組的有序性
數組中各元素的順序和插入順序一致,這個是怎么實現的呢?
為了實現 PHP 數組的有序性,PHP 底層的散列表在散列函數與元素數組之間加了一層映射表,這個映射表也是一個數組,大小和存儲元素的數組相同,存儲元素的類型為整型,用于保存元素在實際存儲的有序數組中的下標 —— 元素按照先后順序依次插入實際存儲數組,然后將其數組下標按照散列函數散列出來的位置存儲在新加的映射表中:
這樣,就可以完成最終存儲數據的有序性了。
PHP 數組底層結構中并沒有顯式標識這個中間映射表,而是與 arData 放到了一起,在數組初始化的時候并不僅僅分配用于存儲 Bucket 的內存,還會分配相同數量的 uint32_t 大小的空間,這兩塊空間是一起分配的,然后將 arData 偏移到存儲元素數組的位置,而這個中間映射表就可以通過 arData 向前訪問到。
總結
PHP中的數組其特點就是將 values 映射到 keys 的類型。與其他語言不同的是,PHP中數組的 key 可以是字符串,而values可以是任意類型。
除常規增刪改查之外,數組還有很多其他操作,比如復制、合并、銷毀、重置等,這些操作對應的代碼都位于 zend_hash.c 中,感興趣的同學可以去了解一下。
推薦學習:《PHP視頻教程》