初始化StringBuilder以使用UTF-16编码器

时间:2019-05-30 10:19:55

标签: java stringbuilder java-11

考虑Java 11中的以下代码:

StringBuilder sb = new StringBuilder("one");
sb.append("δύο");  // "two"

第一行创建一个使用Latin1编码器(每个字符一个字节)的StringBuilder。然后第二行使StringBuilder意识到它需要使用UTF16编码器来代替,因此在附加新的UTF-16字符之前,它将其当前内容复制到新的数组中。

StringBuilder类具有一个带有初始容量参数的构造函数重载,如果您已经知道要构建的字符串的所需大小,则可以避免重新分配。但是,如果您以英语字符串开头,然后附加一个外部字符串,则此特殊的构造方法重载是无用的,因为它仍会重新分配字节数组。

是否有一种方法可以创建从一开始就使用UTF16的StringBuilder实例?

3 个答案:

答案 0 :(得分:3)

$data = DB::table('test_result') ->join('users', 'users.id', '=', 'test_result.user_id') ->select('users.name','users.image','test_result.*') ->whereDate('test_result.result_time','<=',$r->result_time) ->where('test_result.test_id',$r->test_id) ->orderBy('marks','DESC')->orderBy('take_time', 'ASC') ->get(); { "message": "success", "status": true, "data": [ { "name": "Surender", "image": null, "id": 1, "user_id": 5232, "test_id": 2, "marks": 4, "result_time": "2019-05-30 10:50:12", "take_time": 46, "insert_time": "2019-05-30 11:00:00" } ] }的Java 11或Java 12版本中,没有什么可以做到的。

真正的问题是,从中获得的性能提升对您来说有多重要。 配置您的应用程序,以了解这种不必要的重新分配是否对您的应用程序的总体性能产生了重大影响。

如果这将产生重大影响,则可以实现自己的版本StringBuilder(扩展相同的接口以实现兼容性)。

或者,如果您准备等待,则可以下载OpenJDK源代码并开发/构建/测试StringBuilder ...的扩展,然后将其作为补丁提交以供考虑。 (如果您提供的基准测试显示出明显的性能优势,那么这将有助于提高其被纳入的机会。)

答案 1 :(得分:1)

似乎没有明显的一个。如果您想影响StringBuffer的初始化方式,我的建议是创建一个实现CharSequence的实用程序“ initializer”,并使用相应的StringBuilder构造函数。您可以使用它传递任何长度和char内容,并且StringBuilder内部应该足够聪明才能使用它。

不过,看一下OpenJDK 11的实现,无论如何,从Latin1开始似乎都是一帆风顺的。某种形式的重新分配似乎总是会发生。

答案 2 :(得分:1)

对此进行了更多研究,我为自己的问题提供了另一个答案(Stack Overflow表示回答您自己的问题是完全可以接受的。)

Slawomir says一样,无论如何,StringBuilder都使用Latin1进行初始化。因此,假设您主要使用俄语,中文,北印度语或希腊语等语言进行写作。您想要构建一个已经知道最大大小的字符串,因此可以使用初始容量参数:

StringBuilder sb = new StringBuilder(4096);
sb.append("Здравствуйте!");  // Should easily fit in 4 kilobytes, right?

但是,上述对append的调用将丢弃您先前初始化的4KB缓冲区,并分配一个新缓冲区。为了避免重新分配缓冲区,您使用初始容量构造了StringBuilder,但是无论如何,StringBuilder都会重新分配它。即使它已经足够大,它也重新分配了它!

一种解决方法是使用JVM选项-XX:-CompactStrings运行Java。

如果您始终使用这些语言之一,那么您的字符串将始终使用UTF-16,因此在启动时关闭字符串压缩将减少检查您提供的每个字符串以查看是否可以使用Latin1编码存储的字符串的开销。

另请参见Heinz Kabutz's talk at jPrime Bulgaria, 29 May 2019,由于该“功能”,他使StringBuilder的内存不足。