《Java编程的逻辑》笔记29--剖析String

29.剖析String.png

基本用法

String name = "老马说编程";
String name = new String("老马说编程");
String可以直接使用+和+=运算符
String name = "老马"; name+= "说编程"; 
String descritpion = ",探索编程本质";
System.out.println(name+descritpion);

输出为:老马说编程,探索编程本质

方法

判断字符串是否为空

public boolean isEmpty()

获取字符串长度

public int length()

取子字符串

public String substring(int beginIndex)public String substring(int beginIndex, int endIndex)

在字符串中查找字符或子字符串,返回第一个找到的索引位置,没找到返回-1

 public int indexOf(int ch)
public int indexOf(String str)

从后面查找字符或子字符串,返回从后面数的第一个索引位置,没找到返回-1

public int lastIndexOf(int ch)
public int lastIndexOf(String str)

判断字符串中是否包含指定的字符序列。回顾一下,CharSequence是一个接口,String也实现了CharSequence

public boolean contains(CharSequence s)

判断字符串是否以给定子字符串开头

public boolean startsWith(String prefix)

判断字符串是否以给定子字符串结尾

public boolean endsWith(String suffix)

与其他字符串比较,看内容是否相同

public boolean equals(Object anObject)

忽略大小写,与其他字符串进行比较,看内容是否相同

public boolean equalsIgnoreCase(String anotherString)

String也实现了Comparable接口,可以比较字符串大小

 public int compareTo(String anotherString)

还可以忽略大小写,进行大小比较

public int compareToIgnoreCase(String str)

所有字符转换为大写字符,返回新字符串,原字符串不变

 public String toUpperCase()

所有字符转换为小写字符,返回新字符串,原字符串不变

public String toLowerCase()

字符串连接,返回当前字符串和参数字符串合并后的字符串,原字符串不变

public String concat(String str)

字符串替换,替换单个字符,返回新字符串,原字符串不变

public String replace(char oldChar, char newChar)

字符串替换,替换字符序列,返回新字符串,原字符串不变

 public String replace(CharSequence target, CharSequence replacement)

删掉开头和结尾的空格,返回新字符串,原字符串不变

public String trim()

分隔字符串,返回分隔后的子字符串数组,原字符串不变

public String[] split(String regex)

例如,按逗号分隔"hello,world":

String str = "hello,world"; String[] arr = str.split(",");

arr[0]为"hello", arr[1]为"world"。

走进String内部

  • 封装字符数组
    String类内部用一个字符数组表示字符串,实例变量定义为:
private final char value[];

String有两个构造方法,可以根据char数组创建String

 public String(char value[])
 public String(char value[], int offset, int count)

返回指定索引位置的char

public char charAt(int index)

返回字符串对应的char数组

public char[] toCharArray()

注意,返回的是一个拷贝后的数组,而不是原数组。
将char数组中指定范围的字符拷贝入目标数组指定位置

public void getChars(int srcBegin, int srcEnd, char dst[], int dstBegin)

按Code Point处理字符
与Character类似,String类也提供了一些方法,按Code Point对字符串进行处理。

public int codePointAt(int index)
public int codePointBefore(int index)public int codePointCount(int beginIndex, int endIndex)
public int offsetByCodePoints(int index, int codePointOffset)
  • 编码转换
    Java使用Charset这个类表示各种编码,它有两个常用静态方法:
public static Charset defaultCharset()
public static Charset forName(String charsetName)

第一个方法返回系统的默认编码,比如,在我的电脑上,执行如下语句:

System.out.println(Charset.defaultCharset().name());

输出为UTF-8
第二方法返回给定编码名称的Charset对象,与我们在第六节介绍的编码相对应,其charset名称可以是:US-ASCII, ISO-8859-1, windows-1252, GB2312, GBK, GB18030, Big5, UTF-8,比如:

Charset charset = Charset.forName("GB18030");

String类提供了如下方法,返回字符串按给定编码的字节表示:

public byte[] getBytes() public byte[] getBytes(String charsetName)
 public byte[] getBytes(Charset charset)

第一个方法没有编码参数,使用系统默认编码,第二方法参数为编码名称,第三个为Charset。
String类有如下构造方法,可以根据字节和编码创建字符串,也就是说,根据给定编码的字节表示,创建Java的内部表示。

public String(byte bytes[])public String(byte bytes[], int offset, int length)
public String(byte bytes[], int offset, int length, String charsetName)
public String(byte bytes[], int offset, int length, Charset charset)
public String(byte bytes[], String charsetName)
public String(byte bytes[], Charset charset)

不可变性

与包装类类似,String类也是不可变类,即对象一旦创建,就没有办法修改了。String类也声明为了final,不能被继承,内部char数组value也是final的,初始化后就不能再变了。
String类中提供了很多看似修改的方法,其实是通过创建新的String对象来实现的,原来的String对象不会被修改。比如说,我们来看concat()方法的代码:

public String concat(String str) {
    int otherLen = str.length();
    if (otherLen == 0) {
        return this;
    }
    int len = value.length;
    char buf[] = Arrays.copyOf(value, len + otherLen);
    str.getChars(buf, len);
    return new String(buf, true);
}

通过Arrays.copyOf方法创建了一块新的字符数组,拷贝原内容,然后通过new创建了一个新的String。
与包装类类似,定义为不可变类,程序可以更为简单、安全、容易理解。但如果频繁修改字符串,而每次修改都新建一个字符串,性能太低,这时,应该考虑Java中的另两个类StringBuilder和StringBuffer,我们在下节介绍它们。

常量字符串

它自己就像一个String类型的对象一样,可以直接调用String的各种方法
当通过常量的形式使用一个字符串的时候,使用的就是常量池中的那个对应的String类型的对象
通过常量直接赋值返回true,而是通过new创建的,==就不会返回true

hashCode

private int hash; // Default to 0

第一次调用hashCode()的时候,会把结果保存在hash这个变量中,以后再调用就直接返回保存的值

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;
}

如果缓存的hash不为0,就直接返回了,否则根据字符数组中的内容计算hash,计算方法是: s[0]31^(n-1) + s[1]31^(n-2) + ... + s[n-1] s表示字符串,s[0]表示第一个字符,n表示字符串长度,s[0]*31^(n-1)表示31的n-1次方再乘以第一个字符的值

正则表达式

分隔字符串

 public String[] split(String regex) 

检查是否匹配

public boolean matches(String regex)

字符串替换

public String replaceFirst(String regex, String replacement)  public String replaceAll(String regex, String replacement)
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 214,377评论 6 496
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 91,390评论 3 389
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 159,967评论 0 349
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,344评论 1 288
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,441评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,492评论 1 292
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,497评论 3 412
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,274评论 0 269
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,732评论 1 307
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,008评论 2 328
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,184评论 1 342
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,837评论 4 337
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,520评论 3 322
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,156评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,407评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,056评论 2 365
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,074评论 2 352

推荐阅读更多精彩内容