C语言中字符串只能使⽤字符数组或者字符指针表示,而java引入了String来表示字符串,C在计算机中存储是Ascll存储,java中字符串的存储:unicode存储,java8及以前一个字符占用2个字节,Java9及之后采用byte存储,即一个字符占用1个字节,有些占用2个字节(汉字,表情符号等)

String

一.String原理介绍

 1.字符串构造

总之,java的字符串构造方法非常多,这4种是最常见的,其他的按照需求可以去查找

https://docs.oracle.com/en/java/javase/17/docs/api/java.base/java/lang/String.html
2. 字符串内存存储

 (1). 字符串常量池在JVM中是StringTable类,实际是⼀个固定⼤⼩的HashTable

(2).内存存储

 String  s  = "hello";
 String  s1 = "hello";
 System.out.println(s == s1);
 //结果:true

内存布局:

      只要由双引号引起的字符串都存储在常量池中

 存储方法:进行存储时,先检查池中有没有该对象"hello",没有就存储“hello”; 否则就直接将“”hello的地址存储在引用中,所以结果为ture

二.常⽤⽅法介绍

1.比较

(1). ==比较符,对于内置类型(int byte等)来说,==比较的是值

int a = 10;
int b = 20;
System.out.println(a==b);
//结果为 true

对于引用类型来说,==比较的是内存

 String  s  = new String("hello");
 String  s1 = new String("hello");
 System.out.println(s == s1);
 //结果:false

(2).字符串equals(返回值为布尔型):比较的是引用对象的值,则按照字典序(字符⼤⼩的顺序)来比较字符串

String  s  = new String("hello");
String  s1 = new String("hello");
System.out.println(s.equals(s1));
 //结果:true

(3).compareTo(返回值为int): 按照字典序进⾏⽐较

1. 先按照字典次序⼤⼩⽐较,如果出现不等的字符,直接返回这两个字符的⼤⼩差值
2. 如果前k个字符相等(k为两个字符⻓度最⼩值),返回值两个字符串⻓度差值
String  s  = new String("abc");
String  s1 = new String("hello");
System.out.println(s.compareTo(s1));
//结果: -7

(4).compareToIgnoreCase ⽅法:与compareTo⽅式相同,但是忽略⼤⼩写⽐较

String  s  = new String("HELLO");
String  s1 = new String("hello");
System.out.println(s.compareToIgnoreCase(s1));// 0
//返回值都是 int
2.字符串查找

(1). char charAt(int index):读取字符串第index个元素

 String  s1 = new String("hello");
 System.out.println(s1.charAt(1));// e
 System.out.println(s1.charAt(3));// l
 System.out.println(s1.charAt(5));//报错

(2).int indexOf( char ch):返回第一个ch元素的下标,没有返回-1

String  s1 = new String("hello");
System.out.println(s1.indexOf('e'));// 1
System.out.println(s1.indexOf('o'));// 4
System.out.println(s1.indexOf('p'));// -1(因为没有元素p)

(3).int indexOf(int ch,int formindex):从formindex下标开始找第一次ch出现的下标,没有返回-1

String  s1 = new String("hello");
System.out.println(s1.indexOf('e',1));// 1
System.out.println(s1.indexOf('o',10));//-1,没找到
System.out.println(s1.indexOf('p',0));// -1(因为没有元素p)

(4).int indexOf( String str):返回str第一次出现的位置,没有返回-1

String s1 = new String("acababed");
System.out.println(s1.indexOf("ab"));// 2
System.out.println(s1.indexOf("fc"));// -1

(5).int indexOf( String str,int formindex):从formindex下标开始找第一次str出现的位置,没有返回-1

String s1 = new String("acababed");
System.out.println(s1.indexOf("ab",2));// 2
System.out.println(s1.indexOf("fc",3));// -1
System.out.println(s1.indexOf("a",100));//-1,没找到

(6).int lastIndexOf(char ch):从后向前返回第一个ch元素的下标,没有返回-1

(7).int lastIndexOf(char ch,int formindex):从formindex下标开始从后向前找第一次ch出现的位置,没有返回-1

(8).int lastIndexOf(String str):从后向前返回第一个str元素的下标,没有返回-1

(9).int lastIndexOf(String str,int formindex):从formindex下标开始从后向前找第一次str出现的位置,没有返回-1

重构方法非常多,这里就不一一列举了

3. 数值和字符串转化

数值转字符串

字符串转数值

int data1 = Integer.parseInt("1234");//包装类.parse类型
double data2 = Double.parseDouble("12.34");//包装类.parse类型
boolean b = Boolean.parseBoolean(s3);
4.⼤⼩写转换(这些都是一个一个修改的)
String s1 = "hello";
String s2 = "HELLO";
// ⼩写转⼤写
System.out.println(s1.toUpperCase());
// ⼤写转⼩写
System.out.println(s2.toLowerCase());
5.字符串和数组的转换
 String s = "hello";
// 字符串转数组
char[] ch = s.toCharArray();
//就可以 循环打印了
for (int i = 0; i < ch.length; i++) {
System.out.print(ch[i]);
}
// 数组转字符串
String s2 = new String(ch);
System.out.println(s2);
6.格式化
String s = String.format("%d-%d-%d", 2025, 3,22);
System.out.println(s);//2025-3-22
7.字符串替换
1.String replaceAll(str regex,str replacement) 替换所有指定的内容
2.String replaceFirst(str regex,str replacement) 替换第一个指定的内容
String str = "helloworld" ;
System.out.println(str.replaceAll("l", "_"));//he__owor_d
System.out.println(str.replaceFirst("l", "6666"));//he6666loworld
注意事项: 由于字符串是不可变对象, 替换不修改当前字符串, ⽽是产⽣⼀个新的字符串,并将其给str
8.字符串拆分
 1. String[] split(String regex) 将字符串按照regex全部拆分
 2. String[] split(String regex,int limit) 将字符串按照regex拆分为几组
String str = "hello world hello bit" ;
String[] result = str.split(" ") ; // 按照空格拆分
for(String s: result) {
      System.out.println(s);
}
String str = "hello world hello bit" ;
String[] result = str.split(" ",2) ;
for(String s: result) {
      System.out.println(s);
}
//hello 
//world hello bit
另外有些特殊字符作为分割符可能⽆法正确切分, 需要加上转义字符
eg:拆分IP地址
 String str = "192.168.1.1" ;
//转义字符形式:\+要转义的字符
//但split 不认识 \.  所以再加一个 \
//java中\\表示:第一个 \ 说明后面\. 是个转义字符
String[] result = str.split("\\.") ;
for(String s: result) {
      System.out.println(s);
}
(1) . 字符"|","*","+"都得加上转义字符,前⾯加上 "\\" .
(2) . ⽽如果是 "\" ,那么就得写成 "\\\\" .
 //按照 \ 来分割,写成"192\168\1\1"不行,因为 \168  \1  \1都是转义字符
//所以 写成"192\\168\\1\\1",让 斜杆就是斜杠,不在表示转义
String str = "192\\168\\1\\1" ;
// 但 \\ split分割不了,要写成转义字符即:\\\,但split不认识他,所以再加上 \
// 意思:第一个 \ 说明 \\\ 是个转义字符
String[] result = str.split("\\\\") ;
for(String s: result) {
    System.out.println(s);
}
//192
//168
//1
//1

(3).如果⼀个字符串中有多个分隔符,可以⽤"|"作为连字符

 //遇到 = 和 + 就分割
String str = "name=zhang+san&age=18";
//                          正则表达式
String[] result = str.split("[=|+]") ;
for(String s: result) {
       System.out.println(s);
}

还可以这样:

String str = "name=zhangsan&age=18" ;
String[] result = str.split("&") ;
for (int i = 0; i < result.length; i++) {
String[] temp = result[i].split("=") ;
System.out.println(temp[0]+" = "+temp[1]);
}
9.字符串截取(java中从a->b都是左闭右开)
 1.String substring(int begingIndex) 从指定位置截取到尾部
 2.String substring(int begingIndex,int endIndex) 从beging位置截取到end位置,左闭右开
String str = "helloworld" ;
System.out.println(str.substring(5));//word
System.out.println(str.substring(0, 5));//hello
10.字符串去除空格
  String trim() 去除字符串两边的所有空格,只保留中间的
String str = "    hello world    " ;
System.out.println("["+str+"]");//[    hello world    ]
System.out.println("["+str.trim()+"]");//[hello world]
11.intern⽅法:入池操作

比如:

char[] ch = new char[]{'a', 'b', 'c'};
String s1 = new String(ch); // s1对象并不在常量池中
String s2 = "abc"; // s2创建时放在常量池中
System.out.println(s1 == s2);
//运行结果:true

内存分布:

解释这里的str1,这一步是操作数组变为字符串

 首先,栈区str1指向堆区新开辟的空间,接着调用构造方法String(ch),把数组ch传递过去用value来接收,所以这里有个value,此时再对value指向的对象开始操作(开始转换),所以说这里有个value指向数组ch,这一步相当于借助value产生字符串“abc”放在0x99887744这块空间里

此时加上intern()方法,相当于把str1的对象(前提池中没有该对象)放在池中

内存图:

可以明显看到,把str1对象放在池中

此时给str2赋值时,因为池中有abc对象,所以直接把该地址返回

那如果入池前就有呢??他会返回池中的字符串abc的地址

char[] ch = new char[]{'a', 'b', 'c'};
String s2 = "abc";
String s1 = new String(ch);
s1.intern();
System.out.println(s1 == s2);
//答案为:false

结果应该是true,为什莫为false?

首先把s2的abc放在池中(因为池中没有abc)

接着s2在堆区new了一块空间,该空间内放着abc(只有字面字符串自动放在池中)

接着调用intern()开始入池,因为s1对象里有abc,所以会返回池中abc的地址返回地址了没人接收呀,所以此时s1还是指向原来空间地址,所以结果:false

加上:s1 =s1.intern(),下面是内存演示

此时intern还未执行,地址不一样

这样就true了

三.字符串修改

1.在Java中,字符串被创建后不允许修改

 看一下这个奇怪的案例

你会发现尝试修改后值变了,这是因为在堆中又开辟了一块空间,存的值为ABC,然后s1指向ABC,原来的abc被回收了,下面这张图明显展示了地址的变化

那么万一那天某个代码我需要不停的修改字符串,这种就不行了,因为每一次修改都要进行 指向新的 回收旧的 这两个动作,太费时间了,那有没有始终指向同一个字符串且多次修改都在原有的字符串进行的类呢?有的兄弟,有的

2.StringBuilder类 和 StringBuffer类

介绍:由于String的不可更改特性,为了⽅便字符串的修改,Java中⼜提供StringBuilder和StringBuffer类。,这两个类⼤部分功能是相同的,所以在一起介绍

(1).初始化

//StringBuilder stringBuilder = "66";
//StringBuffer stringBuffer = "66";
//都会报错,虽然这两个类始都是操作同一个字符串,但不是String类,只能实例化创造字符串
StringBuffer  stringBuffer = new StringBuffer("66");
StringBuilder stringBuilder = new StringBuilder("66");

(2).使用

StringBuffer  stringBuffer = new StringBuffer("hello");
stringBuffer.deleteCharAt(0);//删除下标的元素
stringBuffer.append("word");//将字符串变为StringBuffer,并在后面加上该字符串
//String变为StringBuffer: 利⽤StringBuilder的构造⽅法或append()⽅法
//StringBuffer变为String:利用toString()方法

这里StringBuilderStringBuffer的例子都一样,就不一一演示了

(3).这三种字符串时间差值

那末这三种对字符串的修改时间快慢如何??写个代码

 //这个类似于C语言时间戳,毫秒级计算当前时间
long start = System.currentTimeMillis();
String s = "";
for (int i = 0; i < 100000; ++i) {
      s += i;
}
long end = System.currentTimeMillis();
//计算时间差值
System.out.println(end - start);

start = System.currentTimeMillis();
StringBuffer sbf = new StringBuffer("");
for (int i = 0; i < 100000; ++i) {
      sbf.append(i);
}
end = System.currentTimeMillis();
System.out.println(end - start);

start = System.currentTimeMillis();
StringBuilder sbd = new StringBuilder();
for (int i = 0; i < 100000; ++i) {
       sbd.append(i);
}
end = System.currentTimeMillis();
System.out.println(end - start);

当然这里还有许多相应的方法,详解请看

https://docs.oracle.com/en/java/javase/17/docs/api/java.base/java/lang/StringBuilder.html
到这里String就完结了,如果对你有帮助,点个赞在走吧~~
Logo

2万人民币佣金等你来拿,中德社区发起者X.Lab,联合德国优秀企业对接开发项目,领取项目得佣金!!!

更多推荐