差点忘了最常用的String类型,我们对String的大多数方法都已经很熟了,这里就挑几个平时不会直接接触的点来解析一下。

先来看看它的成员变量

public final class String  {
private final char value[];
private int hash; // Default to 0
}
  • string的内容其实就是一个char数组;
  • hash字段缓存了string的哈希值,因为string经常作为hashmap的key,这样能提高性能;

hashCode

public int hashCode() {
int h = hash;
if (h == 0 && value.length > 0) {
char val[] = value; for (int i = 0; i < value.length; i++) {
h = 31 * h + val[i];
}
hash = h;
}
return h;
}

String的哈希值采用一种延迟计算的策略,计算方法很简单,就是把每个char都当做int,通过公式h=31*h+char的计算最终值。由于String是不可变对象,在生命周期内,hash值只需要计算一次。

subString

public String substring(int beginIndex, int endIndex) {
return ((beginIndex == 0) && (endIndex == value.length)) ? this
: new String(value, beginIndex, subLen);
}
public String(char value[], int offset, int count) {
this.value = Arrays.copyOfRange(value, offset, offset+count);
}

注:上面的代码为了节省空间,省略了异常检查逻辑

subString会创建一个全新的字符串,而不是共享原字符串的char数组。按道理讲,由于String是不可变的,那么subString和原string共享char数组是安全的,可能是出于其他方面的考虑:虽然节省了一点空间,但是需要额外增加一个offset和size成员,整体效率未必更佳。

码点(CodePoint)

简单介绍一下码点和码元的概念,一个码点是某种字符编码方案里面,某个字符对应的绝对编码值。而码元则是指具体的字符存储方案下,最小的存储单元。

对java的String来说,存储的是unicode字符,使用的编码方案是utf-16,码元是char(16bit); utf-16的大部分码点用一个char足够了,但是有少部分需要两个char。

我们来看一段从码点序列创建String的代码:

public String(int[] codePoints, int offset, int count) {
final int end = offset + count; // Pass 1: Compute precise size of char[]
int n = count;
for (int i = offset; i < end; i++) {
int c = codePoints[i];
if (Character.isBmpCodePoint(c))
continue;
else if (Character.isValidCodePoint(c))
n++;
else throw new IllegalArgumentException(Integer.toString(c));
} // Pass 2: Allocate and fill in char[]
final char[] v = new char[n]; for (int i = offset, j = 0; i < end; i++, j++) {
int c = codePoints[i];
if (Character.isBmpCodePoint(c))
v[j] = (char)c;
else
Character.toSurrogates(c, v, j++);
} this.value = v;
}
  • 同样,上面的代码删除了异常处理逻辑;

  • 请注意,码点用int来表示

  • 第一个循环,计算码点数组codePoints,需要多少长度的char数组:

    • Character.isBmpCodePoint 判断是否一个基本多文种平面码点,这样的码点只需1个char
    • 否则需要两个码点,长度+1
  • 第二个循环,把码点值经过转换存入char数组

    • 如果是基本码点,直接放入
    • 如果是非基本码点,需要做一个计算,生成两个char

因此,如果你要把String当做一段实际的文本,并处理当中的单个文字,通过遍历char的方式是不行的,而要使用codePoint相关方法。关于编码相关的知识,不是本文要讲的内容,大家自行查阅资料。

最新文章

  1. SSH网上答题系统质量属性
  2. flex mxmlc 手动编译项目
  3. 如何修改DBSNMP和SYSMAN用户的密码
  4. Android_Nexus4_屏幕截图
  5. nyoj 90 整数划分
  6. Android开发-API指南-&lt;manifest&gt;
  7. 年过三十,我为什么要学习ios 与安卓App 移动端技术
  8. 手机扫描二维码下载APP,根据操作系统不同自动下载
  9. sql server单表导入、导出
  10. [.NET Framework学习笔记]一些概念
  11. Vb.net/VB 声明API功能父窗口功能
  12. idea基本使用1
  13. spoj mgame
  14. MySQL索引的使用方式和缺点
  15. kappa系数
  16. webpack 处理CSS
  17. HDU 2175
  18. Reading RxJava Marble Diagrams
  19. TOC之关键链项目管理遇到软件project7原则
  20. Jackson反序列化提示:Can not deserialize instance of Task out of START_ARRAY token

热门文章

  1. element-ui 表格错行
  2. iOS应用开发---返回到指定界面
  3. stm32 SPI-FLASH W25Q64
  4. SUSE Ceph RBD Mirror - Storage 6
  5. 《Python编程:从入门到实践》第二章 变量和简单数据类型 习题答案
  6. java 从上至下打印二叉树
  7. Luogu P5020 货币系统
  8. 基于Java+Selenium的WebUI自动化测试框架(三)------记录LOG
  9. 织梦阿里云OSS解决方案
  10. 解决在macOS下安装了python却没有pip命令的问题【经验总结】