Node.js也能用的StringBuilder


有學過Java的人應該會知道「StringBuilder」或是「StringBuffer」這兩個在「java.lang」套件下的類別,常被用來處理需要一直被改變內容的字串。由於Java程式語言一個字串(String)有著不可變物件(Immutable Object)的特性,如果直接使用String類別來進行字串的處理,在改變字串的過程中,每次字串內容的變化將會產生出新的String物件來表示,也導致其效能不是很好,需要使用內建的「StringBuilder」或是「StringBuffer」這兩個類別來專門處理可變的字串,處理完後再使用其「toString()」方法將最終結果建立為字串物件。那麼既然Java需要使用「StringBuilder」或是「StringBuffer」來處理字串,基於JavaScript的Node.js也需要嗎?

Node.js使用Chrome的V8 JavaScript引擎來執行JavaScript程式,而實際上V8實作的字串功能,效能也已經可以說是極好的了,所以官方也無內建「StringBuilder」或是「StringBuffer」之類的模組。也就是說,在Node.js中,可以不需要特別使用「StringBuilder」或是「StringBuffer」來提升字串效能。

然而,「StringBuilder」或是「StringBuffer」帶來的價值僅僅只是字串處理效能而已嗎?不!Java的「StringBuilder」和「StringBuffer」皆自帶了常用的增、刪、改、查之方法,可以大幅度地減少重複撰寫的程式。

舉例來說,若要將某一段字串插入到某個字串中,如果不使用「StringBuilder」或「StringBuffer」,寫出來的Java程式看起來會像這樣:

利用字串物件的「substring」方法將「text」字串變數所表示的字串切割成頭、尾兩個部份,再用「+」運算子將他們串接,並在兩者中間插入新字串。由這一系列的動作來完成我們所謂的「字串插入」。

但如果使用「StringBuilder」或「StringBuffer」,這個Java程式會變得十分簡單,如下:

直接使用StringBuilder物件的「insert」方法,將指定字串插入至指定位置。程式看起來也更容易閱讀。

當然,程式設計者也可以將使用「substring」方法來完成「字串插入」的動作自己另外寫成方法來呼叫,但這樣做的話,之後字串處理的過程中,如果遇到需要刪除或是取代的時候不也要再實作一次嗎?直接使用「StringBuilder」或「StringBuffer」會省事很多。

從剛剛就一直在說「StringBuilder」和「StringBuffer」,這兩者究竟差在哪裡呢?其實,這兩者的用法完全一樣,只差在「StringBuilder」類別在多執行緒的條件下是不安全的,而「StringBuffer」類別則是擁有thread-safe的特性。若無多執行緒需求的話,使用「StringBuilder」類型會比較好,因為不用花費效能去處理同步問題。

Java的內容講了一堆,回到Node.js的主題上吧!Node.js是單執行緒的結構,也就是說,同一時間不會有CPU同時執行某段程式的問題。若要在Node.js上實作如Java內建的「StringBuilder」或「StringBuffer」,可以不必考慮thread-safe的問題,因此只需要有「StringBuilder」就好。

node-stringbuilder

node-stringbuilder」是一個使用Node.js 8之後才支援的N-API所開發的模組,使用C語言和UTF-16編碼,在一段長度可變的記憶體內來處理字串的相關操作,支援String、Buffer、ReadStream、Number、Boolean和其他物件的輸入。同時它也內建字串搜尋的功能,使用「Boyer-Moore-MagicLen演算法。且每個物件皆能複製出新的獨立物件來進行不一樣的字串處理。

GitHub:

https://github.com/magiclen/node-stringbuilder

npm:

https://www.npmjs.com/package/node-stringbuilder

安裝

直接使用npm指令進行安裝:

npm install --save node-stringbuilder

用法

初始化

使用「require」函數來引入「node-stringbuilder」模組。

接著使用「new」運算子,或是使用模組的「from」方法來建立StringBuilder物件。

建構參數可以傳入預設的文字內容和長度容量。

長度容量可以分成好幾個區塊,每個長度容量的區塊是128(個字元)。長度容量可以區塊為單位進行擴充或是縮小。

當有文字加入至StringBuilder物件中時,StringBuilder會去檢查它的長度容量是否足夠容納這新進來的文字。如果不行,它就會自動進行擴展,當然,擴展長度容量的時候會有一些延遲,如果頻繁地執行擴展的動作,甚至會拖慢程式的運行速度。因此,如果程式設計者可以預測這個StringBuilder物件大概會存到多長的文字,建議在產生StringBuilder物件的階段就先行設定。

串接(Append)

串接文字至原本的文字之後。

串接文字至原本的文字之後,並進行換行。

串接文字至原本的文字之後,並重複進行數次。

非同步(asnyc)的方式串接檔案內容至原本的文字之後。

插入(Insert)

插入文字至原本文字中的任意位置。

取代(Replace)

取代原本文字中的指定位置範圍的某段文字。

取代部份原本文字中已存在的子字串。

取代所有原本文字中已存在的子字串。

刪除(Delete)

刪除原本文字中的指定位置範圍的某段文字。

刪除原本文字中指定索引位置的字元。

清空StringBuilder物件,但保留現有的長度容量。

子字串(Substring)

僅保留原本文字中的指定位置範圍的某段文字。

反轉(Reverse)

大小寫轉換(Upper/Lower Case)

將文字轉換成大寫或是小寫。

修剪(Trim)

移除文字前後所有空白、換行相關的字元。

重複(Repeat)

將目前的文字重複數次。

擴展長度容量

擴展StringBuilder物件的長度容量。

擴展StringBuilder物件的長度容量,並取得擴展之後的容量。

縮小長度容量

根據目前的文字縮小StringBuilder物件的長度容量。

根據目前的文字縮小StringBuilder物件的長度容量,並取得縮小之後的容量。

取得目前文字長度

取得長度容量

計算字數

建立字串

將StringBuilder物件內指定位置範圍的文字轉成字串。

將StringBuilder物件內指定位置範圍的文字轉成UTF-8編碼的Buffer。

將StringBuilder物件內的文字都轉成字串。

將StringBuilder物件內的文字都轉成UTF-8編碼的Buffer。

取得StringBuilder物件內指定索引位置的文字字元。

字串搜尋

從文字前端開始搜尋子字串。

從文字前端開始搜尋符合正規表示式的子字串。

從文字尾端開始搜尋子字串。

字串比對

比對兩文字是否完全相等。

比對兩文字是否在忽略大小寫的條件下相等。

比對文字是否以某字串開頭或結尾。

複製StringBuilder物件

效能的影響

由於使用C語言這樣的底層程式實作模組的關係,「node-stringbuilder」的效能大概只有在「串接(Append)」和「字串比對(完全相等)」時會比JS程式還要來的差。雖說如此,這兩者卻也是平常開發產品時最常用的功能,因此如果不需要進行除了「串接(Append)」和「字串比對(完全相等)」之外,其他的字串操作的話,直接使用JavaScript程式原生的方式去產生字串是比較好的。

關於作者

Magic Len

Magic Len

各位好,我是Magic Len,是這網站的管理員。我是台灣台中大肚山上人,畢業於台中高工資訊科和台灣科技大學資訊工程系,曾在桃機航警局服役。我熱愛自然也熱愛科學,喜歡和別人分享自己的知識與經驗。如果你有興趣認識我,可以加我的Facebook,並且請註明是從MagicLen來的。

相關文章