前 言 


最近小编在看《Java核心技术 卷一》,遇到有趣或者难以理解的地方就和大家分享一下。希望我们能共同进步,以梦为马,不负韶华。 字符串遍历似乎是一个很基础同时也很简单的问题,但是字符串遍历真的简单吗?你了解字符在Java中的编码方式吗?相信所有程序员都遇到过各种各样的bug,令人最头疼的无异于找bug和修改bug,“万丈高楼平地起”,为了避免今后写大型项目时bug的出现,打好基础是很有必要的。 话不多说,开始进入正题吧。

python遍历字符串输入成字典 python中字符串的遍历_System



python遍历字符串输入成字典 python中字符串的遍历_Java_02

正 文 


首先需要了解字符在Java中的编码方式。

python遍历字符串输入成字典 python中字符串的遍历_Java_03

01、char类型Collision Resistance

char类型用于表示单个字符,java中一个char类型占据2个字节即16位。

例如: ‘A’是编码为65(十进制)或41(16进制)或0000 0000 0100 0001(2进制,计算机中存放的值)所对应字符常量。 ‘中’是编码为20013(十进制)或4E2D(16进制)所对应字符常量。 ‘国’是编码为22269(十进制)或56FD(16进制)所对应字符常量。

python遍历字符串输入成字典 python中字符串的遍历_Java_03

02、Unicode码

Collision Resistance Unicode是一种字符编码方式,即字符与Unicode码的一一映射

在20世纪80年代开始设计Unicode编码时,人们认为两个字节(16位,共65536个字符)的代码宽度足以能对世界上各种语言的所有字符进行编码,并有足够的空间留给未来扩展。 在1991年发布了Unicode 1.0(\u0000~\uFFFF),仅使用了65536个代码值中不到一半的部分。 遗憾的是,由于引入大量汉语、日语和韩国语言中的表意文字,Unicode字符最终超过了65536个,即16位的char类型不能满足全部的Unicode字符。   所以Java怎么解决这个问题呢? 简单粗糙的理解就是,一部分字符用一个char来表示,另一部分字符用两个char来表示

想要知道具体的实现过程吗,接下来将进行更为细致的解释。 首先定义一个概念“代码点”。

python遍历字符串输入成字典 python中字符串的遍历_Java_03

03、代码点

Collision Resistance 代码点指与一个编码表中的某个字符对应的代码值。代码点采用十六进制书写,并加上前缀U+

专业术语的解释看起来不太好理解,举个简单的例子: 前面提到了‘A’、‘中’、‘国’三个字符的编码,其对应Unicode码分别为\u0041、\u4E2D、\u56FD。其对应的代码点分别为:

字符

代码点

'A'

U+0041

'中'

U+4E2D

'国'

U+56FD


很显然,代码点就是Unicode码的代码值。 以上所举的例子都是在\u0000~\uFFFF (65536个代码值)范围内的字符。在16位的Unicode字符集不够用时,将其扩展为\u000000~\u10FFFF(1114112个代码值)。 例如:整数集合的数学符号‘Z’,Unicode码为\u1D56B

字符

代码点

'Z'(整数集合符号)

U+1D56B

Unicode编码是理论上的研究,技术上的具体实现方法有UTF-8、UTF-16、UTF-32。在Java中,char类型使用UTF-16编码来实现Unicode码。


python遍历字符串输入成字典 python中字符串的遍历_Java_06



python遍历字符串输入成字典 python中字符串的遍历_Java_03

04、代码单元

Collision Resistance

UTF-16编码中两个字节即16位表示一个代码单元。代码单元(code unit):在基础多语言级别中,每个字符用16位表示(即代码单元);而辅助字符采用一对连续的代码单元进行编码.



python遍历字符串输入成字典 python中字符串的遍历_Java_03

05、UTF-16编码

Collision Resistance UTF-16编码采用不同长度的编码表示所有的Unicode代码点。首先将Unicode代码点分为两部分,一部分是基本的多语言级别(\u0000~\uFFFF),另一部分是辅助字符(\u10000~\10FFFF)。 其中基本的多语言级别中每个字符用16位表示即一个代码单元(一个char);辅助字符采用两个代码单元(char[2])进行编码。


python遍历字符串输入成字典 python中字符串的遍历_py遍历字符串的每个字符_09


如上图显示了UTF-16编码与Unicode码的对应关系。UTF-16深灰色部分与Unicode深灰色部分一一对应,同理浅灰色部分也是一一对应关系。Unicode中\uD800~\uDFFF(2048字节)为空闲区域即不表示任何字符。Unicode中辅助字符使用UTF-16中替代区域进行编码,即一个辅助字符由两个代码单元表示,其中第一个代码单元范围是D800~DBFF,第二个代码单元范围是DC00~DFFF。这种设计十分巧妙,通过判断代码单元的所属范围,就可以很容易的知道该代码单元是一个字符的编码,还是一个辅助字符的第一或第二部分。


字符

代码点

代码单元

'中'

U+4E2D

U+4E2D

'国'

U+56FD

U+56FD

'Z'(整数集合符号)

U+1D56B

U+D835

U+DD68

以上就是代码点和代码单元的全部解释内容,接下来用代码实现一下字符串遍历吧。



python遍历字符串输入成字典 python中字符串的遍历_Java_03

06、应用及实现

Collision Resistance

如何使用Java遍历字符串呢?

String str = "Hello World!";       for(int i=0;i           System.out.print(str.charAt(i));        }


没有学代码点和代码单元的知识时,小编就是这样写的代码,看起来很简单呀。但是要注意length()方法返回的是代码单元的数量charAt()方法返回的是第i个位置的代码单元,这两个方法都是与代码单元有关。

当字符串内包含辅助字符时,这种方法还适用吗? 答案很显然是不适用,因为辅助字符中一个字符由两个代码单元组成,这时应该利用代码点有关的方法来遍历字符串。   codePointCount(0,str.length())

方法:返回代码点数量 codePointAt(i)

方法:返回第i个代码点处的字符,注意返回的是int类型

String str = "\uD875\uDD68 is the set of integers";System.out.println(str);System.out.printf("第一种方法字符总数:%d\n",str.length());//错误的解法for(int i=0;i  System.out.printf("第%d个字符:",i);  System.out.print(str.charAt(i)+" ");}System.out.print('\n');System.out.printf("第二种方法字符总数:%d\n",str.codePointCount(0,str.length()));for(int i=0;i    int ch = str.codePointAt(i);    System.out.printf("第%d个字符:",i);    System.out.print((char)ch);    if(Character.isSupplementaryCodePoint(ch))       i+=2;    else       i++;    }

最 后 


代码点和代码单元在《Java核心技术 卷一》中3.3.3和3.6中都有提到,有兴趣的小伙伴可以去了解一下。 以上内容是否对你学习Java带来了一些帮助和启示呢? 

python遍历字符串输入成字典 python中字符串的遍历_System_11