String
1.8
public final class String
implements java.io.Serializable, Comparable<String>, CharSequence {
/** The value is used for character storage. */
private final char value[];
/** Cache the hash code for the string */
private int hash; // Default to 0
}
得到的信息
-
实现 Serializable 接口支持序列化
-
实现 CharSequence 接口 字符序列
-
final 修饰不可继承!
-
final char value[]; 使用字串数组作为底层实现
初始化方法
字面量
/**
* 字面量创建一个对象
*/
String str1 = "abc";
String str2 = "abc";
构造函数
初始化新创建的字符串对象,使其表示与参数相同的字符序列;换句话说,是新创建的字符串是参数字符串的副本。除非需要原始代码的显式副本,此构造函数的使用是不必要,因为字符串是不可变的。其实通过这样的方式创建一个字符串得到的是参数字符串的副本。
public String(String original) {
this.value = original.value;
this.hash = original.hash;
}
使用字符数组来创建一个String
- this.value = Arrays.copyOf(value, value.length);
- 底层也是直接使用复制的方式创建
public String(char value[]) {
this.value = Arrays.copyOf(value, value.length);
}
StringBuffer
public String(StringBuffer buffer) {
synchronized(buffer) {
this.value = Arrays.copyOf(buffer.getValue(), buffer.length());
}
}
StringBuilder
public String(StringBuilder builder) {
this.value = Arrays.copyOf(builder.getValue(), builder.length());
}
常用函数
得到长度
public int length() {
return value.length;
}
isEmpty
- 使用此函数来判断是否为空只需要判断一次即可
public boolean isEmpty() {
return value.length == 0;
}
toCharArray
转化为字符数组
public char[] toCharArray() {
// Cannot use Arrays.copyOf because of class initialization order issues
char result[] = new char[value.length];
System.arraycopy(value, 0, result, 0, value.length);
return result;
}
指定的索引
public char charAt(int index) {
if ((index < 0) || (index >= value.length)) {
throw new StringIndexOutOfBoundsException(index);
}
return value[index];
}
比较两个字符串
- 首先得到两个字符串的长度
- 得到最小的长度
- 得到两个字符串的 字符数组实现
- 按照最小长度为终点, 遍历笔记两个字符串的每一个字符
- 返回值
- 如果在遍历检查的这个范围之内出现了不一致的字符, 就直接返回两个字符串当前位置字串的差值
- 如果没有出现不一致的字符, 就返回比较串和被比较串长度的差值
- 返回不同位置字符的差值
- 返回两个字符串长度的差值
- 相等的情况也就是会返回两个字符串长度的差值, 也就是 0
public int compareTo(String anotherString) {
int len1 = value.length;
int len2 = anotherString.value.length;
int lim = Math.min(len1, len2);
char v1[] = value;
char v2[] = anotherString.value;
int k = 0;
while (k < lim) {
char c1 = v1[k];
char c2 = v2[k];
if (c1 != c2) {
return c1 - c2;
}
k++;
}
return len1 - len2;
}
equals 方法
比较过程如下:
- 当前对象和传入的对象是同一个对象, 返回真
- 传入的对象如果是String对象, 就开始逐一比较其中的字符
public boolean equals(Object anObject) {
if (this == anObject) {
return true;
}
if (anObject instanceof String) {
String anotherString = (String)anObject;
int n = value.length;
if (n == anotherString.value.length) {
char v1[] = value;
char v2[] = anotherString.value;
int i = 0;
while (n-- != 0) {
if (v1[i] != v2[i])
return false;
i++;
}
return true;
}
}
return false;
}
去除两端的空格
会先得到原有字符串两端出现空格位置的下标!分别用两个变量来存放。只要两端有一端存在空格, 就使用substring(st, len) 来分割字符串, 否则就直接返回原有的字符串。
- st 从头开始遍历得到出现空格的位置
- len 从尾开始遍历得到出现空格的位置
public String trim() {
int len = value.length;
int st = 0;
char[] val = value; /* avoid getfield opcode */
while ((st < len) && (val[st] <= ' ')) {
st++;
}
while ((st < len) && (val[len - 1] <= ' ')) {
len--;
}
return ((st > 0) || (len < value.length)) ? substring(st, len) : this;
}
indexOf
得到元素的下标
- Character. MIN_SUPPLEMENTARY_CODE_POINT是java中的16进制的表示方式,以0x开头代表十六进制,0开头的是八进制。
- Character. MIN_SUPPLEMENTARY_CODE_POINT这个数代表十进制中62355,刚好是2个字节。
public int indexOf(int ch, int fromIndex) {
final int max = value.length;
if (fromIndex < 0) {
fromIndex = 0;
} else if (fromIndex >= max) {
// Note: fromIndex might be near -1>>>1.
return -1;
}
if (ch < Character.MIN_SUPPLEMENTARY_CODE_POINT) {
// handle most cases here (ch is a BMP code point or a
// negative value (invalid code point))
final char[] value = this.value;
for (int i = fromIndex; i < max; i++) {
if (value[i] == ch) {
return i;
}
}
return -1;
} else {
return indexOfSupplementary(ch, fromIndex);
}
}
indexOfSupplementary(int ch, int fromIndex)
private int indexOfSupplementary(int ch, int fromIndex) {
if (Character.isValidCodePoint(ch)) {
final char[] value = this.value;
final char hi = Character.highSurrogate(ch);
final char lo = Character.lowSurrogate(ch);
final int max = value.length - 1;
for (int i = fromIndex; i < max; i++) {
if (value[i] == hi && value[i + 1] == lo) {
return i;
}
}
}
return -1;
}
StringBuffer
线程安全, 不会产生新的对象
StringBuilder
线程不安全, 不会产生新的对象
- CAS 比较并交换
- Unsafe类
- 出现ABA问题
- 原子引用 解决ABA问题, 对应乐观锁的思想
- arraylist 元素去重