为什么String,StringBuffer和StringBuilder类使用字节数组而不是字符数组来存储字符串字符?

时间:2019-01-10 09:35:28

标签: java string stringbuilder java-9 stringbuffer

一个字节不能容纳来自世界上各种语言的字符的unicode。因此,使用字节数组时,我们不能使用不同语言的字符串。为什么这些类使用字节数组而不是字符数组?

更新:

class First
{
        public static void main(String[] args)
        {
                System.out.println();
                String s = "\u0935\u0902\u0926\u0947 \u092e\u093e\u0924\u0930\u092e\u094d";
                String s1 = "वंदे मातरम्";
                System.out.println(sb);
                System.out.println(sb1);
        }
}

我认为上面的字符串每个字符占用两个字节。如何将它们容纳在一个字节中?

4 个答案:

答案 0 :(得分:4)

使用byte[]是Java 9中引入的优化。JEP 254: Compact Strings中描述了此更改的目标/动机。

  

摘要

     

为字符串采用节省空间的内部表示形式。

     

目标

     

提高String类和相关类的空间效率,同时在大多数情况下保持性能,并保留所有相关Java和本机接口的完全兼容性。

     

非目标

     

在字符串的内部表示中使用替代编码(例如UTF-8)不是目标。随后的JEP可能会探索这种方法。

     

动机

     

String类的当前实现将字符存储在char数组中,每个字符使用两个字节(十六位)。从许多不同的应用程序收集的数据表明,字符串是堆使用的主要组成部分,而且,大多数String对象仅包含Latin-1字符。这样的字符只需要存储一个字节,因此此类String对象的内部char数组中的一半空间都没有使用。

     

说明

     

我们建议将String类的内部表示形式从UTF-16字符数组更改为字节数组以及一个编码标志字段。新的String类将存储基于字符串内容编码为ISO-8859-1 / Latin-1(每个字符一个字节)或UTF-16(每个字符两个字节)的字符。编码标记将指示使用哪种编码。

     

与字符串相关的类(例如AbstractStringBuilder,StringBuilder和StringBuffer)将更新为使用相同的表示形式,HotSpot VM的固有字符串操作也将使用相同的表示形式。

     

这纯粹是实现更改,不更改现有的公共接口。没有计划添加任何新的公共API或其他接口。

     

迄今为止完成的原型工作证实了在某些极端情况下预期的内存占用减少,GC活动大大减少以及性能下降的情况。

答案 1 :(得分:2)

  

一个字节不能容纳来自各种字符的unicode   世界语言。因此,使用字节数组时,我们不能使用不同语言的字符串。

字符也不能,因为它们只有16位。为此,您需要一个int。但是每个字符一个int感觉太浪费了。

  

为什么这些类使用字节数组而不是字符数组?

之前,很少有字符串是关于从口头语言中提取的单词的。它们几乎都是计算机代码,仅使用ASCII字符,可以7位编码。每个字符使用16位或更多位会浪费内存。因此,相反,他们以字节为单位进行编码,如果所有字符均为ASCII,则为ASCII;如果不是某些字符,则为UTF-16。这样可以节省内存,如果不能则保持足够的状态。

答案 2 :(得分:1)

作为一种优化,某些虚拟机实现(例如OpenJDK 9 and up)将仅包含ASCII编码字符的字符串存储在字节数组中,与使用@show =1 select id ,name,if @show = 1 begin name ,description, end ,price from tbl 相比,节省了大约一半的空间。

并且由于func downloadFile(fileUrl: URL) { let destination = DownloadRequest.suggestedDownloadDestination(for: .documentDirectory) Alamofire.download(fileUrl, to: destination) .response(completionHandler: { (downloadResponse) in self.dic.url = downloadResponse.destinationURL self.dic.uti = downloadResponse.destinationURL!.uti let rect = CGRect(x: 0, y: 0, width: 100, height: 100) self.dic.presentOpenInMenu(from: rect, in: self.view, animated: true) }) } 通常用于技术内容(与自然语言相对),因此大多数程序中的大多数char[]值都符合该描述(即使代码处理的语言是 不使用ASCII编码的字符(例如阿拉伯语或日语)。 HTML标记,记录器ID,调试输出和类似内容始终可以始终使用这些压缩字符串。

由于没有(官方的,受支持的)实际访问原始数据的方式,并且所有访问都需要通过这些方法进行,因此通常不会引起任何兼容性问题。

答案 3 :(得分:0)

实际上,Java 9和更高版本的Java中的String类可以根据字符串的内容为每个字符使用字节数组的1字节或2字节。 String.java中有一个字段

private final byte coder;

确定字符串中的字符(LATIN1或UTF16)使用的编码。

相关问题