首页 > 其他分享 >jdk9为何要将String的底层实现由char[]改成了byte[]

jdk9为何要将String的底层实现由char[]改成了byte[]

时间:2022-09-22 10:45:47浏览次数:67  
标签:字符 UTF String char jdk9 零件 字节

作者:basic13
链接:https://www.zhihu.com/question/447224628/answer/1759986003
来源:知乎
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

这个特性是JDK9放出来的,主要是为了节约String占用的内存。

众所周知,在大多数Java程序的堆里,String占用的空间最大,并且绝大多数String只有Latin-1字符,这些Latin-1字符只需要1个字节就够了。JDK9之前,JVM因为String使用char数组存储,每个char占2个字节,所以即使字符串只需要1字节/字符,它也要按照2字节/字符进行分配,浪费了一半的内存空间。

JDK9是怎么解决这个问题的呢?一个字符串出来的时候判断,它是不是只有Latin-1字符,如果是,就按照1字节/字符的规格进行分配内存,如果不是,就按照2字节/字符的规格进行分配(UTF-16编码),提高了内存使用率。

举个类似的例子说就是,工厂生产的有多种型号的零件,一批零件必须装入同一种型号的包装发货,零件有大号和小号两种,而且绝大多数都是小号,之前包装的时候不管一批零件是大是小全部放到大号的包装里,造成了空间浪费,现在如果一批里面有大号就全装大号,如果没有大号就全装小号,提升了空间利用率。

这种做法带来的好处是显而易见的:

  • 原本一个仓库装不下的零件,现在可以装下了(用更少的内存跑更大的应用)
  • 原本仓库一天往外运一次,现在可以一天半甚至两天运一次(减少GC次数)

为什么用UTF-16而不用UTF-8呢,这就要从这两个字符集的设计说起了。

UTF-8实际上是对空间利用效率最高的编码集,它是不定长的,可以最大限度利用内存和网络。它是小包装装得下就用小包装,小包装装就看看能不能用大包装装,大包装都装不下就用超大包装。但是这种编码集只适用于传输和存储,并不适合拿来做String的底层实现。这是为什么呢?

因为String有随机访问的方法,所谓随机访问,就是charAt、subString这种方法,随便指定一个数字,String要能给出结果。如果字符串中的每个字符占用的内存是不定长的,那么进行随机访问的时候,就需要从头开始数每个字符的长度,才能找到你想要的字符。试想,如果大小包装混装,你想拿到第N个零件,你必须一个一个数包装盒,数到N,才能找到你要的零件。而如果包装是一样的大小,你就可以通过简单的计算知道你要找的零件距离你有多少远,直接过去拿就行了。

但是又有人会问了,UTF-16也是变长的啊,一个字符可能在UTF-16里面占用4个字节咧。是的,是的,UTF-16是变长的,但这是在现实世界里是这样。在java的世界里,一个字符(char)就是2个字节,从\u0000到\uFFFF,占4个字节的字符,在java里是用两个char来存储的,而String的各种操作,都是以java的字符(char)为单位的,charAt是取得第几个char,subString取的也是第几个到第几个char组成的子串,甚至length返回的都是char的个数,从来没有哪个方法可以让你“通过下标取出字符串中第几个'现实意义'中的字符”,所以UTF-16在java的世界里,就可以视为一个定长的编码。

还是工厂的例子:如果哪天出现了一个超大的零件咋办?简单,我这就只有大号包装,一个大号的包装都装不下的时候怎么办呢,把超大号的零件切成两份就行了,用两个大号包装去装,出厂也视为两个零件。

关于这种超大零件,可以试着跑以下下面的代码体会

public class StringTest {
    public static void main(String[] args) {
        System.out.println("

标签:字符,UTF,String,char,jdk9,零件,字节
From: https://www.cnblogs.com/shoshana-kong/p/16718359.html

相关文章

  • vue 中如何使用基于 echarts 的 echarts-wordcloud 插件开发词云图
     echarts-wordcloud词云图官网:https://github.com/ecomfe/echarts-wordcloud 效果如下,每次刷新会随即变换文字颜色 安装npminstallecharts-wordcloudnpm......
  • Vue3 Echarts 省地图
    一、效果 二、echarts的安装npminstallecharts三、echarts各省份地图js导入以下是别人下载好的各省份的数据,可以直接下载使用,放在项目js文件夹下,在页面内引入。......
  • 记录nodejs中querystring‘已弃用’三种处理方法
    一.升级node版本,修改引入方式//升级到18.x版本后修改引入方式constquerystring=require('node:querystring')二.官方推荐URLSearchParams替代因为不想升级就按照......
  • 代码阅读题-int与char运算
    输出是:99100ASCII码:A-65,a-97经测试,将int和char运算输出是int,Java、C++都是盲猜是为了避免运算结果ASCII码非法导致输出? inti=2; intj=i+'b'; chars=......
  • string转wstring
    转载来自:https://www.cnblogs.com/coolbear/archive/2013/05/24/3096683.htmlusingnamespacestd;1、字符串中不含有汉字|--string-->wstringstrings("abc");ws......
  • JDK8中String的intern()方法详细解读【内存图解+多种例子+1.1w字长文】
    写在前面,欢迎大家关注小编的微信公众号!!谢谢大家!!一、前言String字符串在我们日常开发中最常用的,当然还有他的两个兄弟StringBuilder和StringBuilder。他三个的区别也是面......
  • 安装pycharm安装geopandas 成功经验
    本人经验,使用pycharm,10.3版本的python,感觉其他版本的python也能安装得上先安装geopandas依赖的包,下载连接,注意下载自己电脑版本对应的包版本GDAL-3.4.3-cp310-cp310......
  • Codeforces Round #820 (Div. 3) G. Cut Substrings
    DPProblem-G-Codeforces题意给一个长度为\(n(1<=n<=500)\)的主串s,一个长度为\(m(1<=m<=500)\)的模式串t,每次可以将当前的s中与t相同的子串变成一串"."(如......
  • 取消goloand,idea,pycharm等双击shift时出现的全局搜索
    取消goloand,idea,pycharm等双击shift时出现的全局搜索来回切换中英文输入法的时候,goland会弹出来一个搜索框,很不方便,现在要把那个弹出框禁用掉File=>Settings=>Advanc......
  • STL string的查找,比较,截取子串
    compare函数在>时返回1,<时返回-1,==时返回0。比较区分大小写,比较时参考字典顺序,排越前面的越小。大写的A比小写的a小。intcompare(conststring&s)const;//与字符串s......