1、常用方法
01、charAt()
char charAt(int index)
- 返回char指定索引处的值
public static void main(String[] args) {
char c = "乌拉".charAt(1);
System.out.println(c);
}
- 输出
拉
02、compareTo()
int compareTo(String anotherString)
- A.compareTo(B) 如果A和B的内容的头元素一样,比较的是字符串的 长度
- 如果A和B的内容的头元素不一样,比较的是首字母的 ASCII值
示例:
public static void main(String[] args) {
String s1 = "abc";
String s2 = "abcd";
String s3 = "abcdfg";
String s4 = "ab";
String s5 = "1bdasdcdfgsdf";
String s6 = "zabc";
//比较的是长度
System.out.println("s1和s2的比较结果 = " + s1.compareTo(s2)); // -1
System.out.println("s1和s3的比较结果 = " + s1.compareTo(s3)); // -3
System.out.println("s1和s4的比较结果 = " + s1.compareTo(s4)); // 1
System.out.println("s2和s3的比较结果 = " + s2.compareTo(s3)); // -2
//比较的是首字母的ASCII值
//(a的ASCII值为97 1的ASCII值为49 得出 s1比s5大97-49 = 48)
System.out.println("s1和s5的比较结果 = " + s1.compareTo(s5)); // 48
//(a的ASCII值为97 z的ASCII值为122 得出 s1比s5大97-122 = -25)
System.out.println("s1和s6的比较结果 = " + s1.compareTo(s6)); // -25
}
}
输出:
s1和s2的比较结果 = -1
s1和s3的比较结果 = -3
s1和s4的比较结果 = 1
s2和s3的比较结果 = -2
s1和s5的比较结果 = 48
s1和s6的比较结果 = -25
03、contains()
-
boolean contains(CharSequence s)
-
判断前面的字符串中是否包含后面的字符串。包含:true 不包含:false
public static void main(String[] args) {
System.out.println("乌拉".contains("乌"));
System.out.println("www.baidu.com".contains("baidu"));
System.out.println("ABC".contains("123"));
}
- 输出
true
true
false
04、endsWith()
-
boolean endsWith(String suffix)
-
判断当前字符串是否以某个子字符串结尾。是:true 不是:false
public static void main(String[] args) {
System.out.println("test.txt".endsWith("java"));
System.out.println("test.txt".endsWith("txt"));
}
- 输出
false
true
05、equalsIngnoreCase()
boolean equalsIgnoreCase(String anotherString)
- 判断两个字符串是否相等,并且同时忽略大小写
public static void main(String[] args) {
System.out.println("ABC".equalsIgnoreCase("abC"));//true
System.out.println("ABC".equals("abC"));//false
}
- 输出
true
false
06、getbytes()
-
byte[] getBytes(String charsetName)
-
将字符串对象转换成字节数组
public static void main(String[] args) {
byte[] bytes = "abcdef".getBytes();
for (byte byte1:bytes){
System.out.println(byte1);
}
}
- 输出
97
98
99
100
101
102
07、indexof()
int indexOf(String str)
- 判断某个子字符串在当前字符串中第一次出现处的索引(下标)
public static void main(String[] args) {
int a = "oraclejavac++.netc#phppythonjavaoraclec++".indexOf("java");
System.out.println(a);
}
- 输出
6
08、lastIndexOf()
int lastIndexOf(String str)
- 判断某个子字符串在当前字符串中最后一次出现的索引(下标)
public static void main(String[] args) {
int a1 = "oraclejavac++.netc#phppythonjavaoraclec++".lastIndexOf("java");
System.out.println(a1);
}
- 输出
28
09、isEmpty()
boolean isEmpty()
- 判断某个字符串是否为“空字符串”。底层源代码调用的应该是字符串的length()方法。
public static void main(String[] args) {
System.out.println("".isEmpty());
System.out.println("abc".isEmpty());
}
- 输出
true
false
010、length()
int length()
- 面试题:判断数组长度和判断字符串长度不一样
- 判断数组长度是length属性,判断字符串长度是length()方法。
public static void main(String[] args) {
System.out.println("ABCDEF".length());
}
- 输出
6
011、replace()
String replace(CharSequence target, CharSequence replacement)
- String的父接口就是:
CharSequence
- 替换
public static void main(String[] args) {
String replace = "http://www.baidu.com".replace("http", "https");
System.out.println(replace);
}
- 输出
https://www.baidu.com
012、split()
String[] split(String regex)
- 拆分字符串
public static void main(String[] args) {
String[] split = "1998-02-01".split("-");
for (String day:split){
System.out.println(day);
}
}
- 输出
1998
02
01
013、startsWith()
boolean startsWith(String prefix)
- 判断某个字符串是否以某个子字符串开始。
public static void main(String[] args) {
System.out.println("http://www.baidu.com".startsWith("http"));
System.out.println("http://www.baidu.com".startsWith("https"));
}
- 输出
true
false
014、substring()
String substring(int beginIndex)
参数是起始下标- 截取字符串
public static void main(String[] args) {
System.out.println("http://www.baidu.com".substring(7));
}
- 输出
www.baidu.com
String substring(int beginIndex, int endIndex)
- beginIndex起始位置(包括)
- endIndex结束位置(不包括)
public static void main(String[] args) {
System.out.println("http://www.baidu.com".substring(11, 16));
}
- 输出
baidu
015、toCharArray()
char[] toCharArray()
- 将字符串转换成char数组
public static void main(String[] args) {
char[] chars = "乌拉巴拉".toCharArray();
for (char ch:chars){
System.out.println(ch);
}
}
- 输出
乌
拉
巴
拉
016、toLowerCase()
String toLowerCase()
- 转换为小写
public static void main(String[] args) {
String s = "AbCdEf".toLowerCase();
System.out.println(s);
}
- 输出
abcdef
017、toUpperCase()
String toUpperCase();
- 转换为大写。
public static void main(String[] args) {
String s = "AbCdEf".toUpperCase();
System.out.println(s);
}
- 输出
ABCDEF
018、trim()
String trim();
- 去除前后空白
public static void main(String[] args) {
System.out.println(" Hello 乌拉 ".trim());
}
- 输出
Hello 乌拉
019、valueof()
- String中只有这一个方法是静态的,不需要new对象
- 将“非字符串”转换成“字符串”
- 底层调用了
toString
public static void main(String[] args) {
String q1 = String.valueOf(true);
String q2 = String.valueOf(100);
String q3 = String.valueOf(3.14);
if (q1 instanceof String && q2 instanceof String && q3 instanceof String ){
System.out.println("String 类型");
}
}
- 输出
String 类型
2、StringBuffer和StringBuilder
01、StringBuffer
引出StringBuffer
思考:我们在实际的开发中,如果需要进行字符串的频繁拼接,会有什么问题?
- 因为java中的字符串是不可变的,每一次拼接都会产生新字符串。
- 这样会占用大量的方法区内存。造成内存空间的浪费。
- String s = “abc”; s += “hello”;
- 就以上两行代码,就导致在方法区字符串常量池当中创建了3个对象: “abc” “abc” “abchello”
public class StringBufferTest01 {
public static void main(String[] args) {
String s = "";
// 这样做会给java的方法区字符串常量池带来很大的压力。
for(int i = 0; i < 100; i++){
//s += i;
s = s + i;
System.out.println(s);
}
}
}
如果以后需要进行大量字符串的拼接操作,建议使用JDK中自带的:
- java.lang.StringBuffer
- java.lang.StringBuilder
String和StringBuffer底层对比
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Gyt63IsC-1606840425628)(D:\Java项目\00_A_Java笔记\ES笔记配套图片\StringBuffer原理图.png)]
public static void main(String[] args) {
// 创建一个初始化容量为16个char[] 数组。(字符串缓冲区对象)
StringBuffer sb = new StringBuffer();
// 拼接字符串,以后拼接字符串统一调用 append()方法。
// append是追加的意思。
sb.append("a");
sb.append("b");
sb.append("d");
sb.append(3.14);
sb.append(true);
// append方法底层在进行追加的时候,如果char数组满了,会自动扩容。
sb.append(100L);
System.out.println(sb);
}
- 输出
abd3.14true100
如何优化StringBuffer的性能?
- 在创建StringBuffer的时候尽可能给定一个初始化容量。底层是char数组
- 最好减少底层数组的扩容次数。预估计一下,给一个大一些初始化容量。
- 关键点:
给一个合适的初始化容量。可以提高程序的执行效率
。
例如:
public static void main(String[] args) {
// 指定初始化容量的StringBuffer对象(字符串缓冲区对象)
StringBuffer sb = new StringBuffer(100);
sb.append("hello");
sb.append("world");
sb.append("hello");
sb.append("kitty");
System.out.println(sb);
}
- 输出
helloworldhellokitty
02、StringBuilder
public static void main(String[] args) {
// 使用StringBuilder也是可以完成字符串的拼接。
StringBuilder sb = new StringBuilder();
sb.append(100);
sb.append(true);
sb.append("hello");
sb.append("kitty");
System.out.println(sb);
}
- 输出
100truehellokitty
03、区别
StringBuffer和StringBuilder的区别?
- StringBuffer中的方法都有:synchronized关键字修饰。表示StringBuffer在多线程环境下运行是安全的。
- StringBuilder中的方法都没有:synchronized关键字修饰,表示StringBuilder在多线程环境下运行是不安全的。
StringBuffer是线程安全的。
StringBuilder是非线程安全的。
面试题:
1、String为什么是不可变的?
我看过源代码,String类中有一个char[]数组
,这个char[]数组采用了final修饰
,因为数组
一旦创建长度不可变
。并且被final修饰的引用一旦指向某个对象之后,不可再指向其它对象
,所以String是不可变的!“abc” 无法变成 “abcd”
2、StringBuilder/StringBuffer为什么是可变的呢?
我看过源代码,StringBuffer/StringBuilder内部实际上是一个char[]数组
,这个char[]数组没有被final修饰
,StringBuffer/StringBuilder的初始化容量
我记得应该是16
,当存满之后会进行扩容
,底层调用了数组拷贝
的方法
System.arraycopy()
…是这样扩容的。所以StringBuilder/StringBuffer适合于使用字符串的频繁拼接操作。