JAVA的字符串

String&StringBuilder

String的底层数据结构是数组char value[]

1
2
3
4
5
6
7
8
9
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
/** use serialVersionUID from JDK 1.0.2 for interoperability */
private static final long serialVersionUID = -6849794470754667710L;
}

String的类用于存放字符串的方法都用了final来修饰,也就是创建后均不可以被改变,当我们进行一个字符串相连的操作时,便会创建出新的对象

1
2
3
4
5
6
7
8
9
10
String str_1 = new String("ab");
String str_2 = new String("ab");
String str_3 = "ab";


System.out.println(str_1 == str_2); //false
System.out.println(str_1 == str_2.intern());//false
System.out.println(str_1.intern() == str_2.intern());//true
System.out.println(str_1 == str_3);//false
System.out.println(str_1.intern() == str_3);//true

结论:

  1. == , 在引用类型中是对比的地址,比如str1和str2,两个new出来的对象置于堆内存中,地址肯定不同;但是如果是基础类型如str3,就是对比值;当然也有equal方法,这是对比的是哈希值
  2. intern(),这是一个本地方法,底层由c++实现,它的作用是将值推进常量池
  3. String str_3 = "ab"这种赋值方法JVM做了优化,不会创建对象,直接将值放进常量池

StringBuilder

1
2
3
4
5
6
7
8
9
//初始化,同样是数组
new StringBuilder(16);

public StringBuilder() {
super(16);
}
AbstractStringBuilder(int capacity) {
value = new char[capacity];
}
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
26
27
28
//添加元素
stringBuilder.append("a");

public AbstractStringBuilder append(String str) {
if (str == null)
return appendNull();
int len = str.length();
ensureCapacityInternal(count + len);
str.getChars(0, len, value, count);
count += len;
return this;
}

private void ensureCapacityInternal(int minimumCapacity) {
// overflow-conscious code
if (minimumCapacity - value.length > 0)
expandCapacity(minimumCapacity);
}
void expandCapacity(int minimumCapacity) {
int newCapacity = value.length * 2 + 2;
if (newCapacity - minimumCapacity < 0) newCapacity = minimumCapacity;
if (newCapacity < 0) {
if (minimumCapacity < 0) // overflow
throw new OutOfMemoryError();
newCapacity = Integer.MAX_VALUE;
}
value = Arrays.copyOf(value, newCapacity);
}

对字符串的各种操作方法

字符串类

String:不可修改

当使用字符串的相加操作时,不会删掉原字符串,而是在常量池里面新建一个新的String,储存修改后的结果

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
equals();
//boolean比较两个字符串是否相等
compareTo();
//基于每个字符进行Unicode值比较,若完全相等,返回0;小于参数,返回负数;大于参数,返回正数
contains();
//boolean若包含某个字符,返回true
indexOf();
//返回字符第一次出现的索引,未找到则返回-1、
startsWith(); endsWith();
//boolean测试字符串是否以参数为前缀开头;是否以参数为后缀结尾
replaceAll(String regex,String replacement);
//将字符串中的所有的regex替换为replacement
split(String regex);
String[] arr = str.split(",");
//每个字符以regex分割并返回一个string型数组
substring();
//可以接收两个参数,返回这个索引截取的子串
trim();
//删除前置和后置的所有空格
toUpperCase();toLowerCase();
//大小写转换
join("mark","");
//为一系列字符串添加分割符并拼成一个新的字符串

StringBuilder:可以修改,可以在常量池里原地修改字符串

StringBuffer:可以修改,且线程安全,基本与StringBuilder相同

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
append();
//字符串连接
toString();
//返回一个与构建器相同的String
setCharAt(int i, char c);
//把某个位置的字符置为C
insert(int offset, String str/char c);
//在指定位置之前插入字符串或字符
delete(int startIndex,int endIndex);
//删除指定范围内的字符串


deleteCharAt (int index);
//删除某个字符
replace(int start,int end,String str);
//在指定范围内用str替换
reverse();
//字符串反转
substring(int start,int end);
//返回子串

如何将ArrayList转换为数组?

1
2
3
4
5
6
7
8
9
10
ArrayList<Integer> list = new ArrayList<>();
for (int i = 0; i < 10; i++) {
list.add(i);
}
//toArray()会返回一个object数组,所以在对元素进行获取时需要进行类型转换
Object[] o = list.toArray();
for (Object value : o) {
int num = (int) value;
System.out.println(num);
}

JAVA的字符串
http://example.com/post/Java的字符串.html
作者
SamuelZhou
发布于
2022年8月14日
许可协议