java9的String底层实现为什么从char[]改成byte[]
从Java 9开始,String
的底层实现从char[]
改为byte[]
,以提高存储空间效率。在之前的实现中,String
对象使用char[]
存储字符,每个字符占用2个字节(UTF-16编码)。然而,许多字符串(特别是拉丁语系的文本)实际上并不需要这么多空间。因此,改用byte[]
作为底层存储结构可以节省空间,并提高性能。
Java 9引入了一个新的Unicode编码标准——UTF-8。
UTF-8使用变长字节序列来表示Unicode字符,相比于UTF-16,它更加紧凑,更能节省内存空间和提高性能。由于UTF-8是一种可变长度的编码,每个Unicode字符使用的字节数不同,因此无法像UTF-16一样使用固定大小的char数组来表示。
为了适应这种变化,Java的String类在Java 9中进行了改进,使用byte数组来存储字符串。这种改变意味着Java现在可以更好地支持使用UTF-8编码的字符串,并且可以更有效地处理Unicode字符。
此外,使用byte数组存储字符串还有助于提高性能。由于byte数组在处理大量的文本数据时更加高效,因此String类的内部实现现在可以更快地处理字符串操作。
String内部维护了byte数组跟一个char数组?
Java 9中的String类内部同时维护了一个byte数组和一个char数组。byte数组用于存储字符串的字节表示,而char数组用于存储字符串的UTF-16编码表示。
当使用String类的getBytes()方法或者其他将字符串转换为字节数组的方法时,String类会将其内部的char数组按照UTF-8编码转换为一个字节数组并返回。这个字节数组就是字符串的字节表示,也就是使用UTF-8编码表示的字节序列。
相反地,当使用String类的toCharArray()方法或者其他获取字符串的char数组表示的方法时,String类会直接返回其内部维护的char数组,这个char数组就是使用UTF-16编码表示的字符序列。
因此,String类内部同时维护了byte数组和char数组,以便于在需要时可以轻松地进行字符串的字节表示和字符表示之间的转换。
使用byte[]
作为底层存储结构有以下优点:
-
存储空间优化:对于ISO-8859-1编码的字符串,使用
byte[]
可以将存储空间减半,因为每个字符只需要一个字节。这有助于减少内存占用,特别是对于包含大量文本的应用程序。 -
有时更快的操作:某些操作(如字符串比较)可能因使用
byte[]
而更快,特别是对于较短的字符串和主要包含ISO-8859-1字符的字符串。这是因为在这种情况下,可以对字节数组直接执行操作,而无需将其转换为char[]
。 -
字符串拼接优化:字符串拼接操作可以直接在
byte[]
级别执行,而无需将byte[]
转换为char[]
,从而提高效率。
当然,新的实现也引入了一些复杂性,因为Java需要在运行时确定字符串的编码。然而,总体来说,这种改变为Java的String
实现带来了更高的存储空间和性能优势。
ISO-8859-1编码在String中byte数组表示中需要多少个字节
其实上面说的存储空间优化, ASCII码倒是真的用的一个字节,但是ISO-8859-1编码嘛
对于ISO-8859-1编码的字符集中除了ASCII字符以外的字符,它们在UTF-8编码中需要使用多个字节来表示。因此,将包含非ASCII字符的ISO-8859-1字符串表示为UTF-8编码时,其字节表示会比原来的ISO-8859-1编码的字节表示更长
所以当使用String类的getBytes()方法将字符串转换为字节数组时,默认情况下会使用UTF-8编码来表示字符串。在UTF-8编码中,ISO-8859-1编码的字符通常只需要使用一个字节来表示,但是对于某些ISO-8859-1字符,它们在UTF-8编码中需要使用多个字节来表示。