【String】就是对char[]数组进行封装的对象,由三部分组成:

1, char数组:它是String对象所表示的字符串的超集;

2, 3, offset和count,表示了String对象表示的字符串在char数组中的起始段;

String是特定设计的,包含以下三个特点:

1, 不变性: 不变模式immutable,节省了同步和锁等待的消耗;

2, 针对【常量池】的优化:

变量 内存空间 常量池

String str1 = “abc” ———————>

String str2 = “abc” ———————> abc

String str3 = new String(“abc”) —-> str实例 ———>

注意:str1 == str3.intern()是true;str2, str2直接指向常量池中的”abc”,不拷贝;

3,类的final定义;

String的两个构造方法:

public String(char value[]) {

    this.value = Arrays.copyOf(value, value.length);

}

String(char[] value, boolean share) {

    this.value = value;

}

第一个构造方法会构造全新的char[]数组;

第二个构造方法共享了原来的char[]数组;

【内存泄漏】第二个包可见的共享char[]数组的构造方法会导致内存泄露

这个构造方法是空间换时间的策略(很有可能理解为时间换空间,因为share了空间,但这里大多数情况下是阻止大空间的GC);

调用这个构造方法,会使得原始的char[]数组无法被GC,假如原char[]很大,按新的String对象只引用了其中很小的一部分,这就是subString(begin, end)的潜在风险,因为这个方法使用了这个包可见的构造方法返回了新的共享了旧的char[]数组的String对象:

new String(offset + beginIndex, endIndex-beginIndex, value);

包可见的构造方法,客户代码虽然无法使用,但调用以下方法则间接调用了这个构造方法:

Integer.toString;

Long.toString;

String.concat;

String.replace;

String.subString;

String.toLower;

String.toUpper;

String.valueOf;

比如:

String str = new String(new char[10000000]);

String str2 = str.subString(1, 5);

1000000个字符常驻内存,无法GC,因为5个字符串的使用;

【字符串分割】

String.split提供【正则表达式】分割功能:

“a;b,c:d”.split(“[;|,|:]”);

StringTokenizer是分割字符串的迭代器:

StringTokenizer st = new StringTokenizer(orignalString, “;”);

while(st.hasMoreTokens())

st.nextToken();

用String.indexOf和String.subString来分割字符串:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
while(true) {

    String splitStr = null;

    int j = orignalStr.indexOf(';');

    if(j < 0)

        break;

    splitStr = orignalStr.subString(0, j);

    orignalStr = orignalStr.subString(j + 1); //更新string
}

分割性能:split < StringTokenizer < indexOf&subString


【字符串查找】

indexOf(char c)与charAt(int index)是String互补的方法;

用startWith和endsWith进行字符串;

用charAt实现startWith:

if(origStr.charAt(0) == ‘a’ && origStr.charAt(1) == ‘b’ && origStr.char(2) == ‘c’);

用charAt实现endsWith:

if(origStr.charAt(len - 1) == ‘c’ && origStr.charAt(len - 2) == ‘b’ && origStr.char(len - 3) == ‘a’);

charAt性能高于startWith和endsWith;


【字符串连接 + += concat StringBuilder StringBuffer】

静态字符串(String常量)的连接操作,会在编译期被编译器直接运算优化:

String result = “abc + “and” + “123”; 的性能高于

StringBuilder builder = new StringBuilder();

builder.append(“abc”);

因为静态字符串的+操作在编译期就被运算了,运行期只存在”abcand123”一个字符串,并非:

“abc”, “and”, “123”, “abcand”, “abcand123”;

动态字符串(String变量)的连接操作,会在编译期被编译器转换为StringBuilder实现,循环中的局部变量也不例外:

所以,

String str1 = “abc”;

String str2 = “and”;

String str3 = “append”;

String result = str1 + str2 + str3;

的字节码等同于:

String result = (new StringBuilder(String.valueOf(str1))).append(str2).append(str3).toString();

所以,其实用+操作和StringBuilder的性能是一样的 ;

但编译器把+转换为StringBuilder时不够聪明,经常会过多new StringBuilder的对象:

for(int i = 0; i < 10000; i++)

str = str + i;

会被编译器转换为:

for(int i = 0; i < 10000; i++)

str = (new StringBuilder(String.valueOf(str))).append(i).toString();

所以应该显式使用StringBuilder而不是依靠编译器转换为StringBuilder实现:

StringBuilder sb = new StringBuilder();

for(int i = 0; i < 100000; i++)

sb.append(i);

StringBuffer是线程安全的,理论上性能略低于StringBuilder;

StringBuilder和StringBuffer就是变长的char[]数组,跟所有变长数组一样,指定合适capacity可以节省扩容的消耗,提高性能:

StringBuffer(int capacity) StringBuilder(int capacity);

字符串连接的效率:StringBuilder >> concat > +

读书笔记-String的更多相关文章

  1. 2019.03.19 读书笔记 string与stringbuilder的性能

    1 string与stringbuilder 并不是stringbuilder任何时候都在性能上占优势,在少量(大约个位数)的字符串时,并不比普通string操作快. string慢的原因不是stri ...

  2. [读书笔记]C#学习笔记八:StringBuilder与String详解及参数传递问题剖析

    前言 上次在公司开会时有同事分享windebug的知识, 拿的是string字符串Concat拼接 然后用while(true){}死循环的Demo来讲解.其中有提及string操作大量字符串效率低下 ...

  3. 汉字与区位码互转(天天使用的String存储的是内码),几个常见汉字编码,附有读书笔记

    汉=BABA(内码)=-A0A0=2626(区位码)字=D7D6(内码)=-A0A0=5554(区位码) 各种编码查询表:http://bm.kdd.cc/ “啊”字是GB2312之中的第一个汉字,会 ...

  4. 汉字与区位码互转(天天使用Delphi的String存储的是内码,Windows记事本存储的文件也是内码),几个常见汉字的各种编码,utf8与unicode的编码在线查询,附有读书笔记 good

    汉=BABA(内码)=-A0A0=2626(区位码)字=D7D6(内码)=-A0A0=5554(区位码) 各种编码查询表:http://bm.kdd.cc/ 汉(记住它,以后碰到内存里的数值,就会有敏 ...

  5. 《C#本质论》读书笔记(18)多线程处理

    .NET Framework 4.0 看(本质论第3版) .NET Framework 4.5 看(本质论第4版) .NET 4.0为多线程引入了两组新API:TPL(Task Parallel Li ...

  6. 《C#高级编程》读书笔记

    <C#高级编程>读书笔记 C#类型的取值范围 名称 CTS类型 说明 范围 sbyte System.SByte 8位有符号的整数 -128~127(−27−27~27−127−1) sh ...

  7. js读书笔记

    js读书笔记 基本类型的基本函数总结 1. Boolean() 数据类型 转换为true的值 转换为false的值 Boolean true false String 任何非空字符串 "&q ...

  8. 读书笔记:const和readonly、static readonly 那些事

    C#中表示不变的量(常量)的两种形式:const 和readonly const 是静态常量 readonly 是动态常量 严格的来讲:const 应该称为常量 而readonly 则应称为只读变量. ...

  9. C++ 11学习和掌握 ——《深入理解C++ 11:C++11新特性解析和应用》读书笔记(一)

    因为偶然的机会,在图书馆看到<深入理解C++ 11:C++11新特性解析和应用>这本书,大致扫下,受益匪浅,就果断借出来,对于其中的部分内容进行详读并亲自编程测试相关代码,也就有了整理写出 ...

随机推荐

  1. re正则表达式7_{}

    curly brackets {} instead of one number, you can specify a range by writing a minimum,a comma,and a ...

  2. codeforces 697B Barnicle

    题目链接:http://codeforces.com/problemset/problem/697/B 题目大意: 将科学计数法用十进制表示.[如果类似于7.0应输出7] 解题思路: Java 中 B ...

  3. PHP----Ajax异步请求

    需要两个PHP页面:1.php是发出请求和接受请求结果的.2.php是处理请求的结果. 1.php中代码: <a href="#" onclick="sendAja ...

  4. JavaScript Engines

    http://openaphid.github.io/blog/2013/01/17/part-i-how-to-choose-a-javascript-engine-for-ios-and-andr ...

  5. Google 谷歌网页搜索, 学术搜索

    Google 谷歌网页搜索, 学术搜索 1. 网页搜索引擎-Google * https://letsgg.tk/ * https://google.kfd.me/ 谷歌搜索镜像:  http://d ...

  6. MySQL笔记-最简单的方法来解决找不到mysqld.sock文件的问题

    首先,环境:ubuntu 14.04,采用apt-get的方式安装的,手动安装可能路径设置稍有区别. 1.安装MySQL后,用命令行首次启动时发现找不到Mysqld.sock文件,提示: ERROR ...

  7. awk操作数组注意几点

    awk的数组跟其他程序设计语言的数组有所不同:1.可以直接在awk中定义数组:2.数组元素的初始值为0或空字符串,除非他们被显示的指定初始化:3.数组可以自动扩展:4.都是关联数组,数字下标也会转成字 ...

  8. 【Delphi】GIF 动画建立

    var Gif:TGifImage; begin //Setting the delay for each frame TGIFGraphicControlExtension.; TGIFGraphi ...

  9. A股博弈笔记

    A股博弈笔记 @2014/11/07 A股行情最近甚嚣尘上,似乎是牛市的前奏,指数虽然见涨,但赔钱的股民估计也不少,本人就是其中一个,是我在逆势而行吗? 试图追逐价值投资的方式,而钟情于蓝筹股,本来也 ...

  10. Mongodb3.0.6副本集+分片学习笔记

    一.使用问题记录 1. mongodb3.0.6使用mongostat参数 >./mongostat -h 127.0.0.1:27017 -u root -p 123456 /authenti ...