MST
星途 面试题库

面试题:Java String性能优化之底层存储结构与优化策略

从Java 9开始,String的底层存储结构发生了变化,由char数组改为了byte数组。请详细阐述这种变化对String性能优化的影响,包括但不限于内存占用、字符串操作效率等方面。并针对新的存储结构,提出至少两种在实际项目中优化String性能的策略,且说明每种策略的适用场景和可能带来的风险。
26.7万 热度难度
编程语言Java

知识考点

AI 面试

面试题答案

一键面试

变化对性能优化的影响

  1. 内存占用
    • 之前(char数组)char类型在Java中占2个字节,对于仅包含Latin - 1字符集(即ASCII字符集扩展,0 - 255范围)的字符串,会造成空间浪费。例如,一个只包含英文字母的字符串,本来每个字符用1个字节就可以存储,但char数组每个元素占2个字节。
    • 之后(byte数组):Java 9引入了byte数组存储字符串,并且使用encoding - flag来标识字符编码。如果字符串仅包含Latin - 1字符,每个字符用1个字节存储,大大减少了内存占用。对于包含非Latin - 1字符的字符串,会采用UTF - 16编码,每个字符仍占2个字节。总体来说,对于大量仅包含Latin - 1字符的字符串场景,内存占用显著降低。
  2. 字符串操作效率
    • 读取操作:由于byte数组存储对于Latin - 1字符更紧凑,在读取操作时,如果字符串仅包含Latin - 1字符,从内存读取的数据量减少,缓存命中率可能提高,从而提升读取效率。
    • 写入操作:对于仅包含Latin - 1字符的字符串写入操作,由于占用空间变小,在写入时可能减少内存分页等开销,提升写入效率。但对于包含非Latin - 1字符的字符串,由于需要UTF - 16编码转换,可能在写入操作上略有性能损耗。
    • 拼接操作StringBuilderStringBuffer在拼接字符串时,如果是大量Latin - 1字符的字符串,由于底层存储紧凑,拼接过程中的内存复制等操作数据量减少,提升拼接效率。但如果涉及到字符编码转换(如从Latin - 1到UTF - 16或反之),拼接效率可能会受到一定影响。

优化String性能的策略

  1. 策略一:使用String的工厂方法优化内存占用
    • 适用场景:当已知字符串内容仅包含Latin - 1字符时,使用String.valueOf(byte[])String.copyValueOf(byte[])等工厂方法创建String对象。这样可以确保字符串以最紧凑的byte数组(Latin - 1编码)存储,进一步优化内存占用。例如,在处理日志记录中大量的英文字母、数字等仅包含Latin - 1字符的文本时适用。
    • 可能带来的风险:如果错误地将包含非Latin - 1字符的byte数组通过这些方法创建String对象,会导致字符编码错误,出现乱码等问题。
  2. 策略二:避免不必要的字符编码转换
    • 适用场景:在字符串处理过程中,如果明确知道字符串的编码类型且不会改变,尽量避免进行不必要的编码转换操作。例如,在处理从文件读取的固定编码格式(如UTF - 8且仅包含Latin - 1字符子集)的字符串数据时,在整个处理流程中保持其编码一致性,避免转换为其他编码。这样可以减少由于编码转换带来的性能开销。
    • 可能带来的风险:如果后续需要与其他使用不同编码的模块交互,而未进行适当的编码转换,可能导致数据不一致或无法正确处理的问题。例如,在与外部API交互时,API期望的是UTF - 16编码,而本地数据一直保持Latin - 1编码,就会出现问题。