在使用Java编程语言时,我们将继续讨论与建议的实践有关的系列文章,我们将讨论String性能调优。 特别是,我们将重点介绍使用默认编码时如何有效地处理字符到字节和字节到字符的转换。 本文总结了两种提议的自定义方法与两种经典方法(“ String.getBytes() ”和NIO ByteBuffer )的性能比较, 后者将字符转换为字节,反之亦然。

所有讨论的主题均基于用例,这些用例来自于电信行业的关键任务超高性能生产系统的开发。

在阅读本文的每个部分之前,强烈建议您参考相关的Java API文档以获取详细信息和代码示例。

所有测试均针对具有以下特征的Sony Vaio进行:

  • 系统:openSUSE 11.1(x86_64)
  • 处理器(CPU):Intel(R)Core(TM)2 Duo CPU T6670 @ 2.20GHz
  • 处理器速度:1,200.00 MHz
  • 总内存(RAM):2.8 GB
  • Java:OpenJDK 1.6.0_0 64位

应用以下测试配置:

  • 并发工作者线程数:1
  • 每个工作者的测试重复次数:1000000
  • 整体测试次数:100

字符到字节和字节到字符的转换
字符到字节和字节到字符的转换被认为是Java开发人员的常见任务,这些开发人员正在针对网络环境进行编程,处理字节数据流,序列化String对象,实现通信协议等。因此,Java提供了一些实用程序来启用开发人员将String (或字符数组)转换为等效的字节数组,反之亦然。

String类的“ getBytes(charsetName) ”操作可能是将String转换为其等效的字节数组的最常用方法。 由于可以根据所使用的编码方案来不同地表示每个字符,因此,上述操作需要“ charsetName ”以便正确转换String字符也就不足为奇了。 如果未提供“ charsetName ”,则该操作使用平台的默认字符集将String编码为字节序列。

将字符数组转换为其等效字节数组的另一种“经典”方法是使用NIO包的ByteBuffer类。 稍后将提供特定方法的示例代码片段。

与更细粒度的方法相比,上述两种方法虽然非常流行并且毫无争议地易于使用和直接使用,但它们的性能都大大不足。 请记住, 我们不是在字符编码之间进行转换 。 为了在字符编码之间进行转换,您应该使用“ String.getBytes(charsetName) ”或NIO框架方法和实用程序来使用“经典”方法。

当所有要转换的字符均为ASCII字符时,建议的转换方法如下所示:

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;
}

通过将每个字符值转换为等效的字节来构造结果字节数组,因为我们知道所有字符都在ASCII范围内(0 – 127),因此只能占据一个 字节大小。

使用结果字节数组,我们可以通过使用“经典” 字符串构造函数“ new String(byte []) ”转换回原始String 。

对于默认的字符编码,我们可以使用下面显示的方法将String转换为字节数组,反之亦然:

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个字节的大小。 为了将String转换为等效的字节数组,我们将String的每个字符转换为其2字节表示形式。

使用结果字节数组,我们可以使用以下提供的方法将其转换回原始的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字节表示形式构造每个String字符。 使用结果字符数组,我们可以通过使用“经典” 字符串构造函数“ new String(char []) ”将其转换回原始String 。

最后但并非最不重要的一点是,我们提供了两个使用NIO包的示例方法,以便将String转换为其等效的字节数组,反之亦然:

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();
}

对于本文的最后一部分,我们提供了上述字符串到字节数组和字节数组到字符串转换方法的性能比较表。 我们已经使用输入字符串“ test string ”测试了所有方法。

首先将String转换为字节数组的性能比较表:

横轴表示测试运行的次数,纵轴表示每次测试运行的每秒平均事务数(TPS)。 因此,较高的值更好。 不出所料,与“ stringToBytesASCII(String) ”和“ stringToBytesUTFCustom(String) ”建议的方法相比,“ String.getBytes() ”和“ stringToBytesUTFNIO(String) ”方法的执行效果均较差。 如您所见,与“经典”方法相比,我们提出的方法可将TPS提高近30%。

最后将字节数组转换为String的性能对比图:

横轴表示测试运行的次数,纵轴表示每次测试运行的每秒平均事务数(TPS)。 因此,较高的值更好。 不出所料,与“ bytesToStringUTFCustom(byte []) ”建议的方法相比,“ new String(byte []) ”和“ bytesToStringUTFNIO(byte []) ”方法的执行效果均较差。 如您所见,与“ new String(byte []) ”方法相比,我们提出的方法使TPS增长了近15%,与“ bytesToStringUTFNIO(byte []) ”方法相比,TPS增长了近30%。

总之,当您处理字符到字节或字节到字符的转换,而又不想更改所使用的编码时,可以通过使用自定义(细粒度)方法而不是使用提供的“经典”方法来获得卓越的性能。 String类和NIO包。 当将测试字符串转换为等效的字节数组时,与“经典”方法相比,我们提出的方法总体上提高了45%的性能。

快乐编码

贾斯汀

聚苯乙烯

考虑到我们的一些读者提出的使用“ String.charAt(int) ”操作而不是使用“ String.toCharArray() ”来将String字符转换为字节的主张后,我更改了我们提出的方法,并重新执行测试。 如预期的那样,进一步实现了性能提升。 特别地,在TPS 额外 13%的平均增加被记录为“stringToBytesASCII(字符串)”方法和TPS的额外 2%平均增加被记录为“stringToBytesUTFCustom(字符串)”。 因此,您应该使用更改后的方法,因为它们的性能甚至比原始方法还要好。 更新的方法如下所示:

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;
}
相关文章 :
  • Java最佳实践–多线程环境中的DateFormat
  • Java最佳实践–高性能序列化
  • Java最佳实践– Vector vs ArrayList vs HashSet
  • Java最佳实践–字符串性能和精确字符串匹配
  • Java最佳实践–队列之战和链接的ConcurrentHashMap

翻译自: https://www.javacodegeeks.com/2010/11/java-best-practices-char-to-byte-and.html

Java最佳实践– Char到Byte和Byte到Char的转换相关推荐

  1. Java最佳实践–字符串性能和精确字符串匹配

    在使用Java编程语言时,我们将继续讨论与建议的实践有关的系列文章,我们将讨论String性能调优. 我们将专注于如何有效地处理字符串创建, 字符串更改和字符串匹配操作. 此外,我们将提供我们自己的用 ...

  2. Java最佳实践–多线程环境中的DateFormat

    这是有关使用Java编程语言时的拟议实践的系列文章的第一篇. 所有讨论的主题均基于用例,这些用例来自于电信行业的关键任务超高性能生产系统的开发. 在阅读本文的每个部分之前,强烈建议您参考相关的Java ...

  3. Java最佳实践–高性能序列化

    在使用Java编程语言时,我们将继续讨论与建议的实践有关的系列文章,我们将讨论并演示如何将对象序列化用于高性能应用程序. 所有讨论的主题均基于用例,这些用例来自于电信行业的关键任务超高性能生产系统的开 ...

  4. Java最佳实践– Vector vs ArrayList vs HashSet

    在使用Java编程语言时,我们将继续讨论与建议的实践有关的系列文章,我们将在三个最常用的Collection实现类之间进行性能比较. 为了使事情变得更现实,我们将在多线程环境下进行测试,以讨论和演示如 ...

  5. Java最佳实践–队列之战和链接的ConcurrentHashMap

    在使用Java编程语言时,我们将继续讨论与建议的实践有关的系列文章,我们将在四个具有相关语义的流行Queue实现类之间进行性能比较. 为了使事情变得更现实,我们将在多线程环境下进行测试,以讨论和演示如 ...

  6. java最佳实践-线程池

    目录 概念 原理 如何保证线程复用 参数 规范 线程池大小如何确定 估算算法 Demo 其他 自己实现完整的线程池 其他 捕获异常信息 概念 线程池是为了提高程序执行效率,尽量减少线程对象的创建和销毁 ...

  7. 《深入理解OSGi:Equinox原理、应用与最佳实践》一3.2 Bundle状态及转换

    3.2 Bundle状态及转换 "状态"是Bundle在运行期的一项动态属性,不同状态的Bundle具有不同的行为.生命周期层规范定义了Bundle生命周期过程之中的6种状态,分别 ...

  8. java中字符串的精确匹配_Java最佳实践–字符串性能和精确字符串匹配

    java中字符串的精确匹配 在使用Java编程语言时,我们将继续讨论与建议的实践有关的系列文章,我们将讨论String性能调优. 我们将专注于如何有效地处理字符串创建, 字符串更改和字符串匹配操作. ...

  9. java高性能序列化_Java最佳实践–高性能序列化

    java高性能序列化 在使用Java编程语言时,我们将继续讨论与建议的实践有关的系列文章,我们将讨论并演示如何将对象序列化用于高性能应用程序. 所有讨论的主题均基于用例,这些用例源于电信行业关键任务超 ...

最新文章

  1. mongodb使用常用语法,持续更新
  2. opencv resize_树莓派监控摄像头python+picamera或openCV
  3. 自动化运维Python系列(六)之面向对象
  4. POJ 1716 区间最小点个数
  5. 基于python的聊天室_Python实现文字聊天室
  6. oracle虚读,oracle基础 - 若虚夜的个人空间 - OSCHINA - 中文开源技术交流社区
  7. 标准评分卡分数计算原理_评分卡的形式、刻度及应用场景
  8. oracle rac standby,oracle RAC数据库建立STANDBY(二)
  9. Python. 报错: TypeError: issubclass() arg 1 must be a class
  10. 有源带阻和无源带阻的区别_一文看懂AOC有源光缆与DAC高速线缆的差异
  11. java题角色信息管理,java题库专家信息管理系统
  12. DHCP服务以及配置DHCP服务器
  13. R 添加使用mac字体
  14. [专业亲测]Ubuntu16.04安装Nvidia显卡驱动(cuda)--解决你的所有困惑
  15. 数据库作业:关系数据库及相关概念
  16. ubuntu单网卡NAT配置局域网共享上网
  17. 拓扑排序之AOV,关键路径之AOE
  18. 【编程书籍 大系】 计算机开放电子书汇总
  19. Unity VR全景漫游
  20. 计算机网络工程用排线架,什么是网络配线架 网络配线架优势有哪些

热门文章

  1. junit 测试执行顺序_JUnit 5中的测试执行顺序
  2. red hat 4.1.2_安装Red Hat Container Development Kit 2.2版本
  3. 什么是openstack_您在OpenStack Summit 2016上错过了什么
  4. 模拟模型学习 几何布朗运动_Java的几何布朗运动
  5. javaone_JavaOne 2015 –第二十版十大收获
  6. Java EE 8怎么了? (第2部分)
  7. Hibernate中保存与持久性以及saveOrUpdate之间的区别
  8. Spring Boot微服务,Docker和Kubernetes研讨会–第3部分
  9. junit junit_JUnit理论简介
  10. Apache Derby数据库用户和权限