面试题答案
一键面试变化对性能优化的影响
- 内存占用
- 之前(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字符的字符串场景,内存占用显著降低。
- 之前(char数组):
- 字符串操作效率
- 读取操作:由于
byte
数组存储对于Latin - 1字符更紧凑,在读取操作时,如果字符串仅包含Latin - 1字符,从内存读取的数据量减少,缓存命中率可能提高,从而提升读取效率。 - 写入操作:对于仅包含Latin - 1字符的字符串写入操作,由于占用空间变小,在写入时可能减少内存分页等开销,提升写入效率。但对于包含非Latin - 1字符的字符串,由于需要UTF - 16编码转换,可能在写入操作上略有性能损耗。
- 拼接操作:
StringBuilder
和StringBuffer
在拼接字符串时,如果是大量Latin - 1字符的字符串,由于底层存储紧凑,拼接过程中的内存复制等操作数据量减少,提升拼接效率。但如果涉及到字符编码转换(如从Latin - 1到UTF - 16或反之),拼接效率可能会受到一定影响。
- 读取操作:由于
优化String性能的策略
- 策略一:使用
String
的工厂方法优化内存占用- 适用场景:当已知字符串内容仅包含Latin - 1字符时,使用
String.valueOf(byte[])
或String.copyValueOf(byte[])
等工厂方法创建String
对象。这样可以确保字符串以最紧凑的byte
数组(Latin - 1编码)存储,进一步优化内存占用。例如,在处理日志记录中大量的英文字母、数字等仅包含Latin - 1字符的文本时适用。 - 可能带来的风险:如果错误地将包含非Latin - 1字符的
byte
数组通过这些方法创建String
对象,会导致字符编码错误,出现乱码等问题。
- 适用场景:当已知字符串内容仅包含Latin - 1字符时,使用
- 策略二:避免不必要的字符编码转换
- 适用场景:在字符串处理过程中,如果明确知道字符串的编码类型且不会改变,尽量避免进行不必要的编码转换操作。例如,在处理从文件读取的固定编码格式(如UTF - 8且仅包含Latin - 1字符子集)的字符串数据时,在整个处理流程中保持其编码一致性,避免转换为其他编码。这样可以减少由于编码转换带来的性能开销。
- 可能带来的风险:如果后续需要与其他使用不同编码的模块交互,而未进行适当的编码转换,可能导致数据不一致或无法正确处理的问题。例如,在与外部API交互时,API期望的是UTF - 16编码,而本地数据一直保持Latin - 1编码,就会出现问题。