Java最佳实践– Char到Byte和Byte到Char的转换
在使用Java編程語(yǔ)言時(shí),我們將繼續(xù)討論與建議的實(shí)踐有關(guān)的系列文章,我們將討論String性能調(diào)優(yōu)。 特別是,我們將重點(diǎn)介紹使用默認(rèn)編碼時(shí)如何有效地處理字符到字節(jié)和字節(jié)到字符的轉(zhuǎn)換。 本文總結(jié)了兩種提議的自定義方法與兩種經(jīng)典方法(“ String.getBytes() ”和NIO ByteBuffer )的性能比較, 后者將字符轉(zhuǎn)換為字節(jié),反之亦然。
所有討論的主題均基于用例,這些用例來(lái)自于電信行業(yè)的關(guān)鍵任務(wù)超高性能生產(chǎn)系統(tǒng)的開(kāi)發(fā)。
在閱讀本文的每個(gè)部分之前,強(qiáng)烈建議您參考相關(guān)的Java API文檔以獲取詳細(xì)信息和代碼示例。
所有測(cè)試均針對(duì)具有以下特征的Sony Vaio進(jìn)行:
- 系統(tǒng):openSUSE 11.1(x86_64)
- 處理器(CPU):Intel(R)Core(TM)2 Duo CPU T6670 @ 2.20GHz
- 處理器速度:1,200.00 MHz
- 總內(nèi)存(RAM):2.8 GB
- Java:OpenJDK 1.6.0_0 64位
應(yīng)用以下測(cè)試配置:
- 并發(fā)工作者線程數(shù):1
- 每個(gè)工作者的測(cè)試重復(fù)次數(shù):1000000
- 整體測(cè)試次數(shù):100
 字符到字節(jié)和字節(jié)到字符的轉(zhuǎn)換 
 字符到字節(jié)和字節(jié)到字符的轉(zhuǎn)換被認(rèn)為是Java開(kāi)發(fā)人員的常見(jiàn)任務(wù),這些開(kāi)發(fā)人員正在針對(duì)網(wǎng)絡(luò)環(huán)境進(jìn)行編程,處理字節(jié)數(shù)據(jù)流,序列化String對(duì)象,實(shí)現(xiàn)通信協(xié)議等。因此,Java提供了一些實(shí)用程序來(lái)啟用開(kāi)發(fā)人員將String (或字符數(shù)組)轉(zhuǎn)換為等效的字節(jié)數(shù)組,反之亦然。 
String類的“ getBytes(charsetName) ”操作可能是將String轉(zhuǎn)換為其等效的字節(jié)數(shù)組的最常用方法。 由于可以根據(jù)所使用的編碼方案來(lái)不同地表示每個(gè)字符,因此,上述操作需要“ charsetName ”以便正確轉(zhuǎn)換String字符也就不足為奇了。 如果未提供“ charsetName ”,則該操作使用平臺(tái)的默認(rèn)字符集將String編碼為字節(jié)序列。
將字符數(shù)組轉(zhuǎn)換為其等效字節(jié)數(shù)組的另一種“經(jīng)典”方法是使用NIO包的ByteBuffer類。 稍后將提供特定方法的示例代碼片段。
與更細(xì)粒度的方法相比,上述兩種方法雖然非常流行并且毫無(wú)爭(zhēng)議地易于使用和直接使用,但它們的性能都大大不足。 請(qǐng)記住, 我們不是在字符編碼之間進(jìn)行轉(zhuǎn)換 。 為了在字符編碼之間進(jìn)行轉(zhuǎn)換,您應(yīng)該使用“ String.getBytes(charsetName) ”或NIO框架方法和實(shí)用程序來(lái)使用“經(jīng)典”方法。
當(dāng)所有要轉(zhuǎn)換的字符均為ASCII字符時(shí),建議的轉(zhuǎn)換方法如下所示:
public static byte[] stringToBytesASCII(String str) {char[] buffer = str.toCharArray();byte[] b = new byte[buffer.length];for (int i = 0; i < b.length; i++) {b[i] = (byte) buffer[i];}return b; }通過(guò)將每個(gè)字符值轉(zhuǎn)換為等效的字節(jié)來(lái)構(gòu)造結(jié)果字節(jié)數(shù)組,因?yàn)槲覀冎浪凶址荚贏SCII范圍內(nèi)(0 – 127),因此只能占據(jù)一個(gè) 字節(jié)大小。
使用結(jié)果字節(jié)數(shù)組,我們可以通過(guò)使用“經(jīng)典” 字符串構(gòu)造函數(shù)“ new String(byte []) ”轉(zhuǎn)換回原始String 。
對(duì)于默認(rèn)的字符編碼,我們可以使用下面顯示的方法將String轉(zhuǎn)換為字節(jié)數(shù)組,反之亦然:
public static byte[] stringToBytesUTFCustom(String str) {char[] buffer = str.toCharArray();byte[] b = new byte[buffer.length << 1];for(int i = 0; i < buffer.length; i++) {int bpos = i << 1;b[bpos] = (byte) ((buffer[i]&0xFF00)>>8);b[bpos + 1] = (byte) (buffer[i]&0x00FF);}return b; }Java中的每種字符類型都占用2個(gè)字節(jié)的大小。 為了將String轉(zhuǎn)換為等效的字節(jié)數(shù)組,我們將String的每個(gè)字符轉(zhuǎn)換為其2字節(jié)表示形式。
使用結(jié)果字節(jié)數(shù)組,我們可以使用以下提供的方法將其轉(zhuǎn)換回原始的String :
public static String bytesToStringUTFCustom(byte[] bytes) {char[] buffer = new char[bytes.length >> 1];for(int i = 0; i < buffer.length; i++) {int bpos = i << 1;char c = (char)(((bytes[bpos]&0x00FF)<<8) + (bytes[bpos+1]&0x00FF));buffer[i] = c;}return new String(buffer); }我們從其2字節(jié)表示形式構(gòu)造每個(gè)String字符。 使用結(jié)果字符數(shù)組,我們可以通過(guò)使用“經(jīng)典” 字符串構(gòu)造函數(shù)“ new String(char []) ”將其轉(zhuǎn)換回原始String 。
最后但并非最不重要的一點(diǎn)是,我們提供了兩個(gè)使用NIO包的示例方法,以便將String轉(zhuǎn)換為其等效的字節(jié)數(shù)組,反之亦然:
public static byte[] stringToBytesUTFNIO(String str) {char[] buffer = str.toCharArray();byte[] b = new byte[buffer.length << 1];CharBuffer cBuffer = ByteBuffer.wrap(b).asCharBuffer();for(int i = 0; i < buffer.length; i++)cBuffer.put(buffer[i]);return b; }public static String bytesToStringUTFNIO(byte[] bytes) {CharBuffer cBuffer = ByteBuffer.wrap(bytes).asCharBuffer();return cBuffer.toString(); }對(duì)于本文的最后一部分,我們提供了上述字符串到字節(jié)數(shù)組和字節(jié)數(shù)組到字符串轉(zhuǎn)換方法的性能比較表。 我們已經(jīng)使用輸入字符串“ test string ”測(cè)試了所有方法。
首先將String轉(zhuǎn)換為字節(jié)數(shù)組的性能比較表:
橫軸表示測(cè)試運(yùn)行的次數(shù),縱軸表示每次測(cè)試運(yùn)行的每秒平均事務(wù)數(shù)(TPS)。 因此,較高的值更好。 不出所料,與“ stringToBytesASCII(String) ”和“ stringToBytesUTFCustom(String) ”建議的方法相比,“ String.getBytes() ”和“ stringToBytesUTFNIO(String) ”方法的執(zhí)行效果均較差。 如您所見(jiàn),與“經(jīng)典”方法相比,我們提出的方法可將TPS提高近30%。
最后將字節(jié)數(shù)組轉(zhuǎn)換為String的性能對(duì)比圖:
橫軸表示測(cè)試運(yùn)行的次數(shù),縱軸表示每次測(cè)試運(yùn)行的每秒平均事務(wù)數(shù)(TPS)。 因此,較高的值更好。 不出所料,與“ bytesToStringUTFCustom(byte []) ”建議的方法相比,“ new String(byte []) ”和“ bytesToStringUTFNIO(byte []) ”方法的執(zhí)行效果均較差。 如您所見(jiàn),與“ new String(byte []) ”方法相比,我們提出的方法使TPS增長(zhǎng)了近15%,與“ bytesToStringUTFNIO(byte []) ”方法相比,TPS增長(zhǎng)了近30%。
總之,當(dāng)您處理字符到字節(jié)或字節(jié)到字符的轉(zhuǎn)換,而又不想更改所使用的編碼時(shí),可以通過(guò)使用自定義(細(xì)粒度)方法而不是使用提供的“經(jīng)典”方法來(lái)獲得卓越的性能。 String類和NIO包。 當(dāng)將測(cè)試字符串轉(zhuǎn)換為等效的字節(jié)數(shù)組時(shí),與“經(jīng)典”方法相比,我們提出的方法總體上提高了45%的性能。
快樂(lè)編碼
賈斯汀
聚苯乙烯
考慮到我們的一些讀者提出的使用“ String.charAt(int) ”操作而不是使用“ String.toCharArray() ”來(lái)將String字符轉(zhuǎn)換為字節(jié)的主張后,我更改了我們提出的方法,并重新執(zhí)行測(cè)試。 如預(yù)期的那樣,進(jìn)一步實(shí)現(xiàn)了性能提升。 特別地,在TPS 額外 13%的平均增加被記錄為“stringToBytesASCII(字符串)”方法和TPS的額外 2%平均增加被記錄為“stringToBytesUTFCustom(字符串)”。 因此,您應(yīng)該使用更改后的方法,因?yàn)樗鼈兊男阅苌踔帘仍挤椒ㄟ€要好。 更新的方法如下所示:
public static byte[] stringToBytesASCII(String str) {byte[] b = new byte[str.length()];for (int i = 0; i < b.length; i++) {b[i] = (byte) str.charAt(i);}return b; }public static byte[] stringToBytesUTFCustom(String str) {byte[] b = new byte[str.length() << 1];for(int i = 0; i < str.length(); i++) {char strChar = str.charAt(i);int bpos = i << 1;b[bpos] = (byte) ((strChar&0xFF00)>>8);b[bpos + 1] = (byte) (strChar&0x00FF); }return b; } 相關(guān)文章 :- Java最佳實(shí)踐–多線程環(huán)境中的DateFormat
- Java最佳實(shí)踐–高性能序列化
- Java最佳實(shí)踐– Vector vs ArrayList vs HashSet
- Java最佳實(shí)踐–字符串性能和精確字符串匹配
- Java最佳實(shí)踐–隊(duì)列之戰(zhàn)和鏈接的ConcurrentHashMap
翻譯自: https://www.javacodegeeks.com/2010/11/java-best-practices-char-to-byte-and.html
創(chuàng)作挑戰(zhàn)賽新人創(chuàng)作獎(jiǎng)勵(lì)來(lái)咯,堅(jiān)持創(chuàng)作打卡瓜分現(xiàn)金大獎(jiǎng)總結(jié)
以上是生活随笔為你收集整理的Java最佳实践– Char到Byte和Byte到Char的转换的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
 
                            
                        - 上一篇: 带有Spring和Maven教程的JAX
- 下一篇: Java最佳实践–队列之战和链接的Con
