上文中我們學(xué)習(xí)了 DS 擴(kuò)展中一些比較常用的數(shù)據(jù)結(jié)構(gòu),也留下了一些伏筆,比如 Map 中返回 keys() 和 values() 分別返回的是兩種特殊的數(shù)據(jù)結(jié)構(gòu),也就是我們今天要學(xué)習(xí)的內(nèi)容。
最初見(jiàn)到 Vector 還是在很早的時(shí)候在 Java 中見(jiàn)過(guò)。不過(guò)即使是在 Java 中,這個(gè)類(lèi)型的數(shù)據(jù)結(jié)構(gòu)的使用也并不多,因?yàn)樵?Java 中也是以 List 和 Map 為主。我們先來(lái)看看這個(gè)集合是怎么用的。
$vector = new \Ds\Vector(["a", "b", "c"]);
$vector->push("d");
$vector->push(5);
$vector->push(6);
$vector->push(7);
$vector->push(8);
$vector->set(3, "ccc");
var_dump($vector->get(3)); // string(3) "ccc"
var_dump($vector->pop()); // int(8)
$vector->unshift(1);
$vector->unshift(-1);
var_dump($vector->shift()); // int(-1)
$vector->insert(5, 'five');
var_dump($vector->get(5)); // string(4) "five"
var_dump($vector->get(6)); // int(5)
$vector->remove(6);
var_dump($vector->get(6)); // int(6)
var_dump($vector[4]); // string(3) "ccc"
$vector[4] = 'Num 4.';
var_dump($vector[4]); // string(6) "Num 4."
var_dump($vector);
// object(Ds\Vector)#1 (8) {
// [0]=>
// int(1)
// [1]=>
// string(1) "a"
// [2]=>
// string(1) "b"
// [3]=>
// string(1) "c"
// [4]=>
// string(6) "Num 4."
// [5]=>
// string(4) "five"
// [6]=>
// int(6)
// [7]=>
// int(7)
// }
它的很多方法和 Map 都是類(lèi)似的,不過(guò)它支持 push()、pop()、shift()、unshift() 這四種方法,也就是分別從尾部和頭部添加和取出數(shù)據(jù)。另外在底層,它使用的總內(nèi)存會(huì)少于使用數(shù)組,當(dāng)分配的內(nèi)存大小降到到足夠低的時(shí)候會(huì)自動(dòng)釋放內(nèi)存。對(duì)于 get()、set()、push()、pop() 這些方法的操作效率都能達(dá)到 O(1) 的水平,而對(duì)于 shift()、unshift()、insert()、remove() 這些操作則都是 O(n) 的水平。至于在什么場(chǎng)景下使用就很清晰了,很大的數(shù)組使用它可以節(jié)約內(nèi)存,并且一些操作的效率還非常高。
在 Map 中使用 values() 和 paris() 返回的就都是 Vector 這個(gè)類(lèi)型的集合。
Set 這個(gè)集合結(jié)構(gòu)其實(shí)挺常見(jiàn)的,不止是 Java 這些編程語(yǔ)言中,redis 中也有這種存儲(chǔ)數(shù)據(jù)的方式,相信大家不會(huì)陌生。和其它結(jié)構(gòu)最顯著的區(qū)別就是 Set 中的值必須是唯一的。
$set = new \Ds\Set(["a", "b", "c"]);
$set->add("d");
$set->add("b");
var_dump($set);
// object(Ds\Set)#2 (4) {
// [0]=>
// string(1) "a"
// [1]=>
// string(1) "b"
// [2]=>
// string(1) "c"
// [3]=>
// string(1) "d"
// }
這個(gè)就不多做解釋了,相信大家就算沒(méi)有在代碼中用過(guò),也會(huì)在 redis 的使用中接觸過(guò),業(yè)務(wù)場(chǎng)景也非常多。在上篇文章中 Map 返回的 keys() 信息就是 Set 結(jié)構(gòu)的,因?yàn)?Map 中的鍵是不能有重復(fù)的,包括數(shù)字下標(biāo)的數(shù)組其實(shí)也都是不能有重復(fù)的鍵值的。
雙端隊(duì)列其實(shí)在表現(xiàn)形式上和 Vector 差不多,同樣可以在隊(duì)列的頭尾部進(jìn)行增加取出操作,不過(guò)它有兩個(gè)指針?lè)謩e指向隊(duì)列的頭尾部,所以它的 shift() 和 unshift() 的速度也是非??斓?O(1) 級(jí)別。
$deque = new \Ds\Deque(["a", "b", "c"]);
$deque->push("d");
$deque->unshift("z");
var_dump($deque);
// object(Ds\Deque)#3 (5) {
// [0]=>
// string(1) "z"
// [1]=>
// string(1) "a"
// [2]=>
// string(1) "b"
// [3]=>
// string(1) "c"
// [4]=>
// string(1) "d"
// }
var_dump($deque->pop()); // string(1) "d"
var_dump($deque->shift()); // string(1) "z"
今天介紹的內(nèi)容相比上篇文章簡(jiǎn)單很多,但上篇文章其實(shí)也只是測(cè)試的代碼結(jié)果展示的比較多而已。整體的 DataStruct 擴(kuò)展框架中的數(shù)據(jù)結(jié)構(gòu)就是這些,就像最開(kāi)始我們說(shuō)過(guò)的,如果沒(méi)有特別的需求,只是需要用到?;蜿?duì)列的話,直接使用 SPL 中的就可以了。而如果有特殊的需求,比如說(shuō) Map 這種對(duì)象類(lèi)型,又或者需要一個(gè)節(jié)約內(nèi)存的數(shù)組,那么 Ds 中的這些數(shù)據(jù)結(jié)構(gòu)想必會(huì)是你的好幫手。
測(cè)試代碼:
https://github.com/zhangyue0503/dev-blog/blob/master/php/2021/02/source/3.一起學(xué)習(xí)PHP中的DS數(shù)據(jù)結(jié)構(gòu)擴(kuò)展(二).php
參考文檔:
https://www.php.net/manual/zh/book.ds.php
聯(lián)系客服