PHP7源码学习笔记(二) HashTable
2020-02-27 本文已影响0人
公式般欢笑
源码版本:php-7.1.0
PHP的数组结构是一种非常灵活的结构,其存储的数据同时包括Java语言中的List和HashMap结构。PHP数组的底层是一个HashTable的结构体,其结构如下:
struct _zend_array {
zend_refcounted_h gc;
union {
struct {
ZEND_ENDIAN_LOHI_4(
zend_uchar flags,
zend_uchar nApplyCount,
zend_uchar nIteratorsCount,
zend_uchar consistency)
} v;
uint32_t flags;
} u;
uint32_t nTableMask;
Bucket *arData; //存储的真实数据的内容
uint32_t nNumUsed; //hashTable中已有的元素个数,包括UNDEF类型的元素
uint32_t nNumOfElements; //hashTable中真是存在的元素个数
uint32_t nTableSize; //hashTable的大小,默认是8,每次扩容增加一倍。
uint32_t nInternalPointer;
zend_long nNextFreeElement;
dtor_func_t pDestructor;
};
typedef struct _Bucket {
zval val;
zend_ulong h; //packedArray中的数值索引或者是 hashArray中的哈希值
zend_string *key; //key的具体内容,例如 $arr['a']=2;这个位置存储的就是‘a’
} Bucket;
hashTable中包含两种数据结构,即packed array 和 hash array。
如果存储的数据是List结构,那么在数组存储过程中,并不会进行hash运算,而是直接存储当前数据的key值。
如果存储的数据是HashMap结构,那么在数据存储过程中,首先要获取当前key的哈希值,而后根据哈希值将数据塞入到对应的bucket中。
如果出现哈希值碰撞的问题,
<?php
$arr=[];
$arr['a']=1;
$arr['b']=2;
假如a与b在进行哈希计算之后,得到了同样的一个值,那么在哈希索引会指向b的bucket,在b的bucket中存入a数据bucket的编号,通过链表的方式,可以取到a的值。