php底层源码之数组

数组key和value的限制条件

 1 <?php
 2 $arr = array(
 3         1 => ‘a‘,
 4         "1" => "b",
 5         1.5 => "c",
 6         true => "d"
 7     );
 8 var_dump($arr);
 9
10 $arr = array(
11         "foo" => "bar",
12         "bar" => "foo",
13         100 => -100,
14         -100 => 100
15     );
16 var_dump($arr);

运行结果:
array (size=1)
1 => string ‘d‘ (length=1)

array (size=4)
‘foo‘ => string ‘bar‘ (length=3)
‘bar‘ => string ‘foo‘ (length=3)
100 => int -100
-100 => int 100

  • ·key 可以是integer或者string
  • ·value 可以使任意类型。

key会有如下的强制转换:

  • ·包含有合法整形值得字符串会被转换为整型
  • ·浮点数和布尔值也会被转换为整型
  • ·键名null实际会被存储为“”
  • ·数组和对象不能被用为键名
  • ·相同键名,之前会被覆盖

数组内部实现:

  • ·实现数组使用了两个数据结构,一个是HashTable,另一个是bucket。
  • ·HashTable结构体用于保存整个数组需要的基本信息。
  • ·Bucket结构体用于保存具体的数据内容

HashTable是什么?
哈希表,是根据关键字(key value)而直接访问在内存存储位置的数据结构。也就是说,它通过把键值通过一个函数的计算,映射到保重一个位置来访问记录,这加快了查找速度。使得普通的查找和插入、杀出操作都可以在O(1)的时间内完成。这个映射函数称作哈希函数,存放记录的数组称作哈希表。

HashTable结构体的表示:

 1 typedef struct _hashtable {
 2     uint nTableSize;            //hash Bucket的大小,最小为8,以二倍增长
 3     uint nTableMask;            //nTableSize-1,索引取值的优化,193491849 & 127
 4     uint nNumOfElements;        //hash Bucket中当前存在的元素个数,count()函数会直接返回此值
 5     ulong nNextFreeElement;        //下一个数字索引的位置
 6     Bucket *pInternalPointer;    //当前遍历的指针,foreach比for快的原因之一,reset,current遍历函数使用
 7     Bucket *pListHead;            //存储数组头元素指针
 8     Bucket *pListTail;            //存储数组尾元素指针
 9     Bucket **arBuckets;            //存储hash数组,实际的存储容器
10     dtor_func_t pDestructor;
11     zend_bool persistent;
12     unsigned char nApplyCount;    //标记当前hash bucket被递归访问的次数(防止多次递归)
13     zend_bool bApplyProtection;
14 #if ZEND_DEBUG
15     int inconsistent;
16 #endif
17 } HashTable;

Bucket结构体:

 1 typedef struct bucket {
 2     ulong h;                        //对char *key进行hash后的值,或者使用户指定的数字索引值
 3     uint nKeyLength;                //hash关键字的长度,如果数组索引为数字,此值为0
 4     void *pData;                    //指向value,一般是用户数据的副本,如果是指针数据,则指向pDataPtr
 5     void *pDataPtr;                    //如果是指针数据,此值会指向真正的value,同时上面pData会指向此值
 6     struct bucket *pListNext;        //整个hash表的下一个元素
 7     struct bucket *pListLast;        //整个hash表表元素的上一个元素
 8     struct bucket *pNext;            //存放在同一个hash Bucket内的下一个元素
 9     struct bucket *pLast;            //同一个hash bucket的上一个元素
10     const char *arKey;                //保存当前key所对应的字符串值
11 } Bucket;

总结成一张图,如下:

原文地址:https://www.cnblogs.com/lxhyty/p/11309126.html

时间: 2024-10-17 18:58:00

php底层源码之数组的相关文章

List集合基础增强底层源码分析

List集合基础增强底层源码分析 作者:Stanley 罗昊 集合分为三个系列,分别为:List.set.map List系列 特点:元素有序可重复 有序指的是元素的添加顺序,也就是说,元素被第一个存进去的时候,它就在第一位,这就是list集合的元素添加顺序: 通常情况下我们所说的有序有两个概念,第一个是添加顺序,第二个是大小顺序(实际上就是元素值的大小) List下面重点关注两个实现类分别是: ArrayList LinkedList ArrayList ArrayList底层实现是数组,既然

模拟jQuery底层源码的链式调用和常用的$()方法的实现

最近在看jQuery框架的源码,感觉还是学到不少东西的,所以就想总结一下自己的知识,和广大的前端爱好者一起 交流一下,我下面所说的并不是直接对jQuery的源码来解读,我是模拟一下jQuery底层源码的链式调用大概是怎么 实现的和常用的$功能是怎么实现的.好了废话不多说了.你要看这个,你就要对jQuery有一定的了解,最起码你要用过jQuery.首先看下jQuery的源码开始是怎么写的 (function( window, undefined){    })(window);它的代码就是被这个块

2018.11.20 Struts2中对结果处理方式分析&amp;struts2内置的方式底层源码剖析

介绍一下struts2内置帮我们封装好的处理结果方式也就是底层源码分析 这是我们的jar包里面找的位置目录 打开往下拉看到result-type节点 name那一列就是我们的type类型取值 上一篇博客在分析的时候发现就算不写也会自动转发原因在这里,default=true 选择了默认方式 接着我们如果想看看底层是如何工作的就选择class属性复制双引号的内容 接着按住ctrl+shift+T就能出现一个框 OPen Type 进去之后发现是这个,点击Attach Source---->选择第二

BAT资深工程师由浅入深分析Tp5&amp;Tp6底层源码 - 分享

BAT资深工程师由浅入深分析Tp5&Tp6底层源码 第1章 课程简介(一定要看,知道整体介绍,方能更好的学习后续课程) 本章主要让大家知道本套课程的主线, 导学内容,如何学习源码等,看完本章要让小伙伴觉得这个是必须要掌握的,并且对加薪有很大的帮助. 第2章 [TP5灵魂]自动加载Loader 深度分析(重点章节,请认真听,建议多次回听) 本章主要讲解为什么要学习自动加载,带领大家看看TP框架的执行流程是什么样子.学习自动加载的原理以及TP5内部自动加载的代码分析.TP 结合composer相关的

HashMap和ConcurrentHashMap的区别,HashMap的底层源码。

Hashmap本质是数组加链表.根据key取得hash值,然后计算出数组下标,如果多个key对应到同一个下标,就用链表串起来,新插入的在前面. ConcurrentHashMap:在hashMap的基础上,ConcurrentHashMap将数据分为多个segment,默认16个(concurrency level),然后每次操作对一个segment加锁,避免多线程锁的几率,提高并发效率. 一.HashMap概述 HashMap基于哈希表的 Map 接口的实现.此实现提供所有可选的映射操作,并允

Java——ArrayList底层源码分析

1.简介 ArrayList 是最常用的 List 实现类,内部是通过数组实现的,它允许对元素进行快速随机访问.数组的缺点是每个元素之间不能有间隔, 当数组大小不满足时需要增加存储能力,就要将已经有数组的数据复制到新的存储空间中. 当从 ArrayList 的中间位置插入或者删除元素时,需要对数组进行复制.移动.代价比较高.因此,它适合随机查找和遍历,不适合插入和删除. 线性表的顺序存储,插入删除元素的时间复杂度为O(n),求表长以及增加元素,取第 i 元素的时间复杂度为O(1). ArrayL

Java——HashMap底层源码分析

1.简介 HashMap 根据键的 hashCode 值存储数据,大多数情况下可以直接定位到它的值,因而具有很快的访问速度,但遍历顺序却是不确定的. HashMap 最多只允许一条记录的key为 null,允许多条value的值为 null. HashMap 非线程安全,即任一时刻可以有多个线程同时写 HashMap,可能会导致数据的不一致.(如果需要满足线程安全,可以用 Collections 的 synchronizedMap 方法使HashMap 具有线程安全的能力,或者使用 Concur

[LeetCode][14]Longest Common Prefix解析 两种算法和底层源码的深入对比-Java实现

Q: Write a function to find the longest common prefix string amongst an array of strings. A: 这题的大概意思就是说给你一组字符串找出其中最长的哪个通用的前缀出来.这个东西不难找,但是如何找的又快又好不简单.其实这题本来就是easy题,但是却让我联想到了<数据结构与算法分析>上的一道题目,那道题目是这样的: 给一个8900个字的字典,从中间找出类似abc.bbc.abb这样单词中只有一个字母不同的单词进行

Java线程池及其底层源码实现分析

1.相关类 Executors  ExecutorService   Callable   ThreadPool     Future 2.相关接口 Executor Executor接口的使用: public class TestExecutor implements Executor{ @Override public void execute(Runnable command){ //调用execute方法常常传入runnable接口对象,开启线程 } } ExecutorService接