目录
一.String类
1.String的特性
(1)String类:代表字符串。
(2)String是一个final类,代表不可变的字符序列。
(3)字符串是常量,用双引号引起来表示。它们的值在创建之后不能更改。
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
2.字符串对象的存储
(1)String对象的字符内容是存储在一个字符数组value[]中的。
(2)字符串常量存储在字符串常量池中,目的是实现共享。字符串非常量对象存储在堆中。
例题:
public class Demo02 {
public static void main(String[] args) {
String s1="javaSE";
String s2="javaSE";
String s3=new String("javaSE");
String s4=new String("javaSE");
System.out.println(s1==s2);//true
System.out.println(s1==s3);//false
System.out.println(s1==s4);//false
System.out.println(s3==s4);//false
}
}
内存图分析:
3.字符串的特性
(1)常量与常量的拼接结果在常量池。且常量池中不会存在相同内容的常量。
(2)只要其中有一个是变量,结果就在堆中。
(3)如果拼接的结果调用intern()方法,返回值就在常量池中。
public class Demo03 {
public static void main(String[] args) {
String s1="hello";
String s2="word";
String s3="hello"+"word";
String s4=s1+"world";
String s5=s1+s2;
String s6=(s1+s2).intern();
System.out.println(s3==s4);//false
System.out.println(s3==s5);//false
System.out.println(s4==s5);//false
System.out.println(s3==s6);//true
}
}
内存图分析:
4.使用String时需要注意的地方
(1)String s1="a" ; 说明:在字符串常量池中创建了一个字面量为“a”的字符串。
(2)s1=s1+"b"; 说明:实际上原来的"a"字符串对象已经丢弃了,现在在堆空间中产生了一个字符串s1+"b"(也就是"ab")。如果多次执行这些改变字符串内容的操作,会导致大量副本字符串对象存留在内存中,降低效率。如果这样的操作放到循环中,会极大影响程序的性能。
(3)String s2="ab"; 说明:直接在字符串常量池中创建一个·字面量为"ab"的字符串。
(4)String s3="a"+"b"; 说明:s3指向字符串常量池中已经创建的"ab"的字符串。
(5)String s4=s1.intern(); 说明:堆空间的s1对象在调用intern()之后,会将常量池中已将存在的"ab"字符串赋值给s4。
5.String 中常用方法
(1)int length(): 返回字符串的长度
(2)char charAt(int index): 返回某索引处的字符
(3)boolean isEmpty():判断是否是空字符串
(4)String toLowerCase():使用默认语言环境,将 String 中的所有字符转换为小写
(5)String toUpperCase():使用默认语言环境,将 String 中的所有字符转换为大写
(6)String trim():返回字符串的副本,忽略前导空白和尾部空白
(7)boolean equals(Object obj):比较字符串的内容是否相同
(8)int compareTo(String anotherString):比较两个字符串的大小
(9)String substring(int beginIndex):返回一个新的字符串,它是此字符串的从 beginIndex开始截取到最后的一个子字符串。
(10)String substring(int beginIndex, int endIndex) :返回一个新字符串,它是此字 符串从beginIndex开始截取到endIndex(不包含)的一个子字符串。
(11)String[] split(String regex):根据给定正则表达式的匹配拆分此字符串。
(12)int indexOf(String str):返回指定子字符串在此字符串中第一次出现处的索引
6.常见算法题目
1.模拟一个trim方法,去除字符串两端的空格。
public class Demo04 {
public static void main(String[] args) {
String str=" XiaoYang ";
String s=Trim(str);
System.out.println("去除两端的空格后,字符串为:"+s);
}
public static String Trim(String str){
if(str == ""){//判断字符串是否为空,如果为空,则返回str
return str;
}else {
int startIndex=0;
int endIndex=0;
char[] arr=str.toCharArray();//将字符串转变成字符数组,方便对单个字符操作
for(int i=0;i<arr.length;i++){//从前往后遍历,找到第一个不为空格的位置并记录下来
if(arr[i]!=' '){
startIndex=i;
break;
}
}
for(int i=arr.length-1;i>=0;i--){从后往前遍历,找到第一个不为空格的位置并记录下来
if(arr[i]!=' '){
endIndex=i;
break;
}
}
return str.substring(startIndex,endIndex+1);//左闭右开
}
}
}
2.将一个字符串进行反转。将字符串中指定部分进行反转。比如“abcdefg”反转为“abfedcg”
public class Demo05 {
public static void main(String[] args) {
String str="abcdefg";
String s=Reverse(str,2,5);
System.out.println("反转后的字符串为:"+s);
}
public static String Reverse(String str,int startIndex,int endIndex){
if(str==null){//判断字符串是否为空
return null;
}else{
char[] arr=str.toCharArray();//将字符串转化成字符数组
for(int i=startIndex,j=endIndex;i<j;i++,j--){//对startIndex-endIndex进行反转
char t=arr[i];
arr[i]=arr[j];
arr[j]=t;
}
return new String(arr);//返回已经反转后的字符串
}
}
}
3.获取一个字符串在另一个字符串中出现的次数。 比如:获取“ ab”在 “abkkcadkabkebfkabkskab” 中出现的次数。
public class Demo06 {
public static void main(String[] args) {
String str="abkkcadkabkebfkabkskab";
String sonStr="ab";
int count=Times(str,sonStr);
System.out.println("子字符串在字符串中出现的次数是"+count);
}
public static int Times(String str,String sonStr){
if(str.length()<sonStr.length()){//判断子字符串要比字符串的长度短
return 0;
}else{
int index,count=0;//定义两个变量,index用于记录找到子字符串的位置,count用于记录找到子字符串的个数
while((index=str.indexOf(sonStr))!=-1){//判断字符串中是否还有子字符串
count++;
/*
找到子字符串后,截取字符串从(index+子字符串的长度)到字符串的末尾
重复此过程,直到字符串中不含有子字符串,返回此时的count值
*/
str=str.substring(index+sonStr.length());
}
return count;
}
}
}
4.获取两个字符串中最大相同子串。比如: str1 = "abcwerthelloyuiodef“;str2 = "cvhellobnm".
public class Demo07 {
public static void main(String[] args) {
String sStr = "cvhellobnm";
String lStr = "abcwerthelloyuiodef";
String s = BigSameStr(sStr, lStr);
System.out.println(s);
}
public static String BigSameStr(String shortStr, String longStr) {
if (shortStr.length() > longStr.length()) {
return null;
}
else {
String str=" ";
/*
利用双层for循环找到长度较短的字符串中所有的子串
判断长字符串是否包含子串,若包含,则跟上一个比较长度
将长度长的子串并且满足包含于长字符串的字符串保存
循环结束最后保存的就是长度最长且包含于长字符串的字符串
*/
for (int i = 0; i < shortStr.length() - 1; i++) {
for (int j = shortStr.length() ; j > i; j--) {
String newStr;
newStr = shortStr.substring(i, j);
if (longStr.contains(newStr) &&newStr.length()>=str.length()) {
str=newStr;
}
}
}
return str;
}
}
}
二.StringBuffer类
1.StringBuffer类的性质
(1)java.lang.StringBuffer代表可变的字符序列,JDK.0中声明,可以对字符串内容进行增删,此时不会产生新的对象。
(2)StringBuffer的很多方法与String相同。
(3)作为参数传递时,方法内部可以改变值。
(4)StringBuffer类不同于String,其对象必须使用构造器生成。有三个构造器:
①StringBuffer():初始容量为16的字符串缓冲区。
②StringBuffer(int size):构造指定容量的字符串缓冲区。
③StringBuffer(String str):将内容初始化为指定字符串内容。
abstract class AbstractStringBuilder implements Appendable, CharSequence {
/**
* The value is used for character storage.
*/
char[] value;//value没有final声明,value可以不断扩容
/**
* The count is the number of characters used.
*/
int count;//count记录有效字符的个数
2.StringBuffer类的常用方法
(1)StringBuffer append(xxx):用于字符串拼接。
(2)StringBuffer delete(int start,int end):删除指定位置的内容。
(3)StringBuffer replace(int start,int end,String str):把[start,end)位置替换为str。(注意左闭右开)
(4)StringBuffer reverse():把当前字符序列逆转
(5)StringBuffer insert(int offset,xxx):在指定位置offset插入xxx。
(6)StringBuffer substring(inr start,int end):在[start,end)截取x新的字符串。(注意左闭右开)
(7)StringBuffer length():返回该字符串的长度。
(8)StringBuffer charAt(int n):返回字符串上n的位置的字符
(9)StringBuffer setCharAt(int n,char ch):将自负床中位置为n的字符变为ch。
注意:①:当使用append和insert方法时,如果原来的value数组长度不够,可扩容。
②:如上这些方法支持方法链操作
③:方法链的原理是:
@Override
public synchronized StringBuffer append(CharSequence s) {
toStringCache = null;
super.append(s);
return this;
}
三.StringBuilder类
1.StringBuilder与StringBuffer非常相似,均可代表可变的字符序列,而且提供相关的方法也一样。
2.相关面试题:
(1)对比String、StringBuffer、StringBuilder
String:不可变字符序列
StringBuffer:可变字符序列、效率低、线程安全。
StringBuilder:可变字符序列、效率高、线程不安全。
注意:作为参数传递的话,方法内部String不会改变其值,StringBuffer与StringBuilder会改变其值。
(2)程序输出:
public class Demo10 {
public static void main(String[] args) {
String str = null;
StringBuffer sb = new StringBuffer();
sb.append(str);
System.out.println(sb.length());//输出:4
System.out.println(sb);//输出:null
StringBuffer sb1 = new StringBuffer(str);
System.out.println(sb1);//输出:
}
}
分析:前边两个输出没有问题,sb拼接str的字符串,此时sb=null,长度为4。第三个输出语句我们便要考虑StringBuffer有参构造器的底层了,,此时编译是没有问题的,但是由于传进去的str为null值,str.length()就会导致出现空指针异常NullPointerException。
public StringBuffer(String str) {
super(str.length() + 16);
append(str);
}
所以正确的在StringBuffer添加null值时 采用下面这个方法:
String str = null;
StringBuffer sb = new StringBuffer();
sb.append(str);