string和StringBuilder解析
更新日期:
1.String之我见
- Java字符串就是Unicode字符序列
- String在java中不是基本类型,是一个类,其实现是通过final char value[],所以查询、替换和数组一样;
- public final class String 说明String 是不可变的,类中每个看起来会修改值的方法都是创建了一个新的对象
就像有个字符串池,字符常量存放在常量池中,字符串变量指向字符串池中的相对应的位置。
实际上,池中的字符串常量是可以共享的。
字符串变量相当于对象变量,是不可以共享的
这样设计是因为字符串很少修改,但是很多时候需要共享,防止出现很多人使用同一字符串时,
有一人修改字符串,而导致的错误 “==”和equals
“==”比较的是s1和s2的内存地址,是一样则返回true
equals比较的是他们的字面量,如果两个字符串是一样的则返回true1
2
3
4
5
6
7
8
9String s1 = new String("ok");//new(),返回的是字符串“ok”在内存中的地址,这里的s1是对象变量保存的是内存地址,
//是不可以共享的
String s12 = new String("ok");
//s1 = s12,则s1 == s12,
System.out.println(s1 == s12);//false
String s2 = "ok";//s2是字符串常量可以共享
String s22 = "ok";
System.out.println(s2 == s22);//truehashCode()
一般情况下,是保存对象的内存地址,但是String中重写了hashCode方法,根据的是字符串的内容生成的,所以如果两个
字符串的内容相同,其hashCode一定相同1
2
3
4
5
6
7
8
9
10
11
12public 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;
}replace:char[] val = value,新的字符数组进行操作,先找到,在替换,之后返回替换后的数组buf[i]
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26public String replace(char oldChar, char newChar) {
if (oldChar != newChar) {
int len = value.length;
int i = -1;
char[] val = value; /* avoid getfield opcode */
while (++i < len) {
if (val[i] == oldChar) {
break;
}
}
if (i < len) {
char buf[] = new char[len];
for (int j = 0; j < i; j++) {
buf[j] = val[j];
}
while (i < len) {
char c = val[i];
buf[i] = (c == oldChar) ? newChar : c;
i++;
}
return new String(buf, true);
}
}
return this;
}
2.StringBuilder
- StringBuilder是从StringBuffer那里演进过来的,StringBuffer是线程安全的,但是StringBuilder并不是线程安全
- StringBuilder,其内部采用动态数组的形式实现,操作的是数组本身拼接完成再将其转换成字符串
实现:
public AbstractStringBuilder append(String str) {if (str == null) str = "null"; int len = str.length(); ensureCapacityInternal(count + len); str.getChars(0, len, value, count); count += len; return this;}
delete:把要被删除元素的后边的元素往前挪了END - START个位置。然后按长度取,insert类似,现将后移,在插入
1
2
3
4
5
6
7
8
9
10
11
12
13
14public AbstractStringBuilder delete(int start, int end) {
if (start < 0)
throw new StringIndexOutOfBoundsException(start);
if (end > count)
end = count;
if (start > end)
throw new StringIndexOutOfBoundsException();
int len = end - start;
if (len > 0) {
System.arraycopy(value, start+len, value, start, count-end);
count -= len;
}
return this;
}