您的位置:首页 > 编程语言 > Java开发

[学习笔记]Java字符串类String

2014-12-14 22:01 337 查看


字符串类(String)


概述

字符串都是对象,是一种特殊的对象。
String类对象是一种常量,一经初始化就不可更改。
可以通过String类的构造器,将其他的字符数组,字节数组或字符按指定编码转换为字符串。


注意

应使用equals()方法比较两个字符串的值是否相等,而不是使用“==”比较符,因为后者比较的是字符串对象地址而非字符串本身。

建议使用:

"content".equals(str)

方法,避免空指针异常。
""为长度为0的字符串对象,而null代表字符串变量没有获取任何字符串对象的引用。要判断字符串既不是null也不是空串可以使用:

if(str!=null&&str.length()!=0)

而且尽量避免在null串上使用方法,将会报空指针异常。


构造器

字节数组(开始位置和长度可选,编码可选)。
字符数组(开始位置和长度可选,编码可选)。
StringBuffer或StringBuilder对象。

创建字符串的方法和区别

Stringstr="java";
Stringstr=newString("java");
Stringstr="Hello"+str;

方法1:直接使用等号创建对象,此时JVM首先查找方法区字符串常量池是否有"java"字符串,如果有则让变量str持有该字符串的引用,如果没有则将字符串"java"驻留在方法区字符串常量池中,并让变量str持有该字符串的引用。

方法2:使用new创建字符串对象,此时创建对象的位置和普通对象一样,在堆区,变量str持有堆区String对象的引用。

方法3:使用字符串连接符“+”创建对象(其中两边至少要有一个是字符串变量),其实相当于使用StringBuffer的append方法创建对象,该字符串存在堆区。

所以当使用方法1创建两个一样字符串的String对象时,其引用的地址是一样的。而使用方法2创建两个相同字符串对象时,其引用的地址是不一样的。


程序

Strings1="java";
Strings2="java";//s1和s2是同一个字符串内存中的引用,String类型字符串为常量
Strings3=newString("java");
Strings4=newString("java");//s3和s4是堆区不同对象的引用,而对象中又持有方法区字符串常量池中"java"的引用
System.out.println(s1==s2);//true
System.out.println(s1.equals(s2));//true
System.out.println(s3==s4);//false
System.out.println(s3.equals(s4));//true


在java中,当同一个字符串字面值出现多次时,在内存中只会保存该字符串的一份拷贝,即s1指向的"java"跟s2指向的"java"在内存中是同一个对象。这种方法叫做“字符串驻留(stringinterning)”。这样编译器就让字符串共享的方式来提高使用效率,该思想称之为享元模式。

而new运算符的作用是在堆内存中创建一个新的对象。因而这里两次new就会在堆中创建两个String对象,尽管它们的字面值是相同的,但其实是两个同不的对象,占两份空间,而对象中实际的字符串"java"是在方法区常量池中的,所以这两个对象也持有该字符串的引用。因此s3==s4自然会返回false了。

如图





所以,当String类使用了字符串连接符“+”,是会创建额外的对象的*,如下代码将创建三个字符串对象。

Stringstr="Hello";

str+="java";

这三个对象分别是"Hello","java","Hellojava"。

*该处仍然有异议,经过验证,通过“+”创建的对象和其他两种方式创建的对象有本质区别。


注意

在Java7以及更新版本中,常量池已经从方法区(永久代,thePermGen)移动到了堆区中,以解决方法区无法扩展内存的窘境。


方法

1.获取字符串长度

intlength()

2.获取指定字符或字符串的位置

intindexOf(intch)

intindexOf(intch,intfromIndex)

intindexOf(Stringstr)

intindexOf(Stringstr,intfromIndex)

获取最后一个指定字符或字符串的位置

intlastIndexOf(intch)

intlastIndexOf(intch,intfromIndex)

intlastIndexOf(Stringstr)

intlastIndexOf(Stringstr,intfromIndex)

3.获取指定位置上的字符

charcharAt(intindex)

4.获取子串(包含头,不包含尾)

Stringsubstring(intbeginIndex)

Stringsubstring(intbeginIndex,intendIndex)

示例:

Stringstr="HeiMa,Cheng,Xu,Yuan";
//1.获取长度
intlength=str.length();//19
//2.获取指定字符的位置,如果没有找到,则返回-1。
intindex=str.indexOf('e');//1
intnextindex=str.indexOf('e',index+1);//8
intlastindex=str.lastIndexOf('a');//17
//3.获取指定位置的字符,如果给定索引位置超出字符串长度,则抛出StringIndexOutOfBoundsException异常。
charch=str.charAt(3);//M
//4.获取子串,包含头,不包含尾。
Stringsubstr1=str.substring(6);//Cheng,Xu,Yuan
Stringsubstr2=str.substring(6,14);//Cheng,Xu


5.判断字符串是否以指定字符或字符串开始和结束

booleanstartsWith(Stringprefix)

booleanstartsWith(Stringprefix,inttoffset)

booleanendsWith(Stringsuffix)

6.判断字符串是否包含指定子串

booleancontains(CharSequences)

7.字符串替换(regex为正则表达式)

Stringreplace(charoldChar,charnewChar)

Stringreplace(CharSequencetarget,CharSequencereplacement)

StringreplaceAll(Stringregex,Stringreplacement)

StringreplaceFirst(Stringregex,Stringreplacement)

8.字符串分割(regex为正则表达式)

String[]split(Stringregex)

String[]split(Stringregex,intlimit)

9.字符串格式化

staticStringformat(Localel,Stringformat,Object...args)

staticStringformat(Stringformat,Object...args)

10.转换字符串大小写

StringtoLowerCase()

StringtoLowerCase(Localelocale)

StringtoUpperCase()

StringtoUpperCase(Localelocale)

示例:

Stringstr="HeiMa,Cheng,Xu,Yuan";
//5.判断字符串是否以指定字符串开头或结尾
booleanb1=str.startsWith("HeiMa");//true
booleanb2=str.endsWith("HeiMa");//false
//6.判断字符串是否包含指定字符串
booleanb3=str.contains("Cheng,Xu");//true
//7.将字符串中指定字符串替换成另一字符串
Stringplacedstr=str.replace("Yuan","Ren");//HeiMa,Cheng,Xu,Ren
//8.将字符串按指定字符分解
String[]strs=str.split(",");//[HeiMa][Cheng][Xu][Yuan]
//9.将格式化字符串
Stringfstr=String.format("%8.2f",12345.6789012);//12345.68
//10.转换字符串大小写
Stringustr=str.toUpperCase();//HEIMA,CHENG,XU,YUAN
Stringlstr=str.toLowerCase();//heima,cheng,xu,yuan


11.将字符串转换为数组

byte[]getBytes()

byte[]getBytes(Charsetcharset)

byte[]getBytes(StringcharsetName)

char[]toCharArray()

12.去除字符串首尾的空白字符

Stringtrim()

13.判断字符串是否为空

booleanisEmpty()

14.将基本数据类型,字符数组或对象转换为字符串

staticStringvalueOf(booleanb)

staticStringvalueOf(charc)

staticStringvalueOf(char[]data)

staticStringvalueOf(char[]data,intoffset,intcount)

staticStringvalueOf(doubled)

staticStringvalueOf(floatf)

staticStringvalueOf(inti)

staticStringvalueOf(longl)

staticStringvalueOf(Objectobj)

15.匹配正则表达式

booleanmatches(Stringregex)

示例:

Stringstr="heima\t";
//11.将字符串转换为数组
byte[]bstr=str.getBytes();
char[]cstr=str.toCharArray();
//12.去除字符串首尾空白字符
Stringtstr=str.trim();//"heima"
//13.判断字符串是否为空
booleanb=str.isEmpty();//false
//14.将基本数据类型转换为字符串
StringfloatStr=String.valueOf(12345.678912);//"12345.678912"
StringobjStr=String.valueOf(newDate());//"SatDec1304:00:57CST2014"
//15.是否匹配正则表达式
booleanrb=str.matches("\\w+");//false


重写Object的方法

1.判断字符串是否相等(系统的默认比较方式)

booleanequals(ObjectanObject)

2.按字典顺序比较字符串(系统的默认比较方式)

intcompareTo(StringanotherString)

3.获取字符串的哈希值(系统的默认比较方式)

inthashCode()

4.获取字符串本身(系统默认的字符串表现形式)

StringtoString()


案例

packagestring;
importjava.util.Arrays;
publicclassStringText{
publicstaticvoidmain(String[]args){
//Case1:对字符串数组进行字典顺序排序。
Stringstrs[]={"hei","ma","cheng","xu","yuan"};
printArray(strs);
sortStrings(strs,0,strs.length-1);
printArray(strs);
printLine();
//Case2:获取字符串中指定字串出现的次数
Stringstr="woiheimatbxqheimaydydheimaxxheimadjscheimabyzdq";
Stringkey="heima";
intcount=getKeyCount(str,key);
System.out.println(str+"\n\""+key+"\"COUNT="+count);
printLine();
//Case3:将字符串中所有字串按长短依次打印
str="itheima";
printAllSubstring(str);
printLine();
//Case4:获取两个字符串的最大相同字串
Stringstr1="woiheimatbxqheimaydydheimaxxheimadjscheimabyzdq";
Stringstr2="woaiheimadanshiwogengaiheimaxxheimahaha";
Stringsame_substring=getSameSubstring(str1,str2);
System.out.println("samesubstring="+same_substring);
printLine();
//Case5:对字符串中字符进行自然顺序排序
str="woiheimatbxqheimaydydheimaxxheimadjscheimabyzdq";
Stringsortstr=sortString(str);
System.out.println("source:\t\t"+str+"\ndestination:\t"+sortstr);
printLine();
//Case6:trim()方法的使用
str="heimaJava";
System.out.println(str.trim());
System.out.println(myTrim(str));
}
/**
*去除字符串首尾的空格
*@paramstr
*@return
*/
publicstaticStringmyTrim(Stringstr){
intstart=0;
intend=str.length()-1;
//循环判断首尾的字符是否是空格,如果是则移动索引继续判断
while(start<=end&&str.charAt(start)==''){
start++;
}
while(start<=end&&str.charAt(end)==''){
end--;
}
//返回没有空格的子串
returnstr.substring(start,end+1);
}
/**
*将字符串中字符按字典顺序排序
*@paramstr
*@return
*/
publicstaticStringsortString(Stringstr){
char[]cs=str.toCharArray();
Arrays.sort(cs);
returnnewString(cs);
}
/**
*获取两个字符串中最大公共子串
*@paramstr1
*@paramstr2
*@return
*/
publicstaticStringgetSameSubstring(Stringstr1,Stringstr2){
//先判断长串和短串
Stringmax;
Stringmin;
max=str1.length()>str2.length()?str1:str2;
min=max.equals(str1)?str2:str1;
for(inti=0;i<min.length();i++){
for(intstart=0,end=min.length()-i;end<=min.length();start++,end++){
//由长到短循环获取短串的所有子串,并判断长串中是否包含,如果包含,则返回这个子串
Stringstr=min.substring(start,end);
if(max.indexOf(str)>=0){
returnstr;
}
}
}
returnnull;
}
/**
*将字符串中所有子串按长短依次打印
*@paramstr
*/
publicstaticvoidprintAllSubstring(Stringstr){
for(inti=0;i<str.length();i++){
//i:整串长度-子串长度
for(intstart=0,end=str.length()-i;end<=str.length();start++,end++){
//索引从0~end开始,每次循环均右移一个字符,直到碰到字符串末尾为止
System.out.print(str.substring(start,end)+"\t");
}
System.out.println();
}
}
/**
*获取字符串str中指定字串key出现的次数
*@paramstr
*@paramkey
*@return
*/
publicstaticintgetKeyCount(Stringstr,Stringkey){
intindex=0;
intcount=0;
while((index=str.indexOf(key,index))!=-1){
index+=key.length();
count++;
}
returncount;
}
/**
*使用快速排序算法对字符串数组排序
*@paramstrs为
*@parama
*@paramb
*/
publicstaticvoidsortStrings(String[]strs,inta,intb){
if(a>=b)return;
inti=a;
intj=b;
Stringstr=strs[i];
while(i<j){
while(strs[j].compareTo(str)>=0&&i<j){
j--;
}
if(i<j){
strs[i]=strs[j];
i++;
}
while(strs[i].compareTo(str)<=0&&i<j){
i++;
}
if(i<j){
strs[j]=strs[i];
j--;
}
}
strs[i]=str;
sortStrings(strs,a,i-1);
sortStrings(strs,i+1,b);
}
/**
*打印字符串数组
*@paramstrs
*/
publicstaticvoidprintArray(String[]strs){
System.out.print("[");
for(inti=0;i<strs.length-1;i++){
System.out.print(strs[i]+",");
}
System.out.println(strs[strs.length-1]+"]");
}
/**
*打印分隔线
*/
publicstaticvoidprintLine(){
System.out.println("-----------------------------");
}
}


运行结果

[hei,ma,cheng,xu,yuan]

[cheng,hei,ma,xu,yuan]

-----------------------------

woiheimatbxqheimaydydheimaxxheimadjscheimabyzdq

"heima"COUNT=5

-----------------------------

itheima

itheimtheima

itheitheimheima

ithetheiheimeima

iththeheieimima

itthheeiimma

itheima

-----------------------------

source1:woiheimatbxqheimaydydheimaxxheimadjscheimabyzdq

source2:woaiheimadanshiwogengaiheimaxxheimahaha

samesubstring=heimaxxheima

-----------------------------

source:woiheimatbxqheimaydydheimaxxheimadjscheimabyzdq

destination:aaaaabbcddddeeeeehhhhhiiiiiijmmmmmoqqstwxxxyyyz

-----------------------------

heimaJava

heimaJava


字符串构建类(StringBuffer/StringBuilder)


概述

由于String类没有提供用于修改字符串的方法,如果希望修改,一个替代的方式是使用subString方法和字符串连接符“+”联合使用来达到目的。但是如果是源自于文件或键盘的单个字符或较短字符串汇成较长字符串,这样就需要这样频繁拼接,在方法区字符串池中就会产生大量的无用的零碎的字符串。为此,应该使用字符串构建类StringBuffer/StringBuilder,该类的特点是在堆区完成字符串的拼接和修改,所以不会产生大量的碎片。


特点

1.是一个字符串缓冲区,其实就是一个容器。

2.长度是可变,可将任意数据都转成字符串进行存储。

3.容器对象提供很多对容器中数据的操作功能,比如:添加,删除,查找,修改。

4.必须所有的数据最终变成一个字符串。

5.StringBuffer和Stringbuilder类只有一个区别:前者是线程安全的,而后者效率较高,优先使用后者。


与数组比较

数组存储完可以单独操作每一个元素,每一个元素都是独立的。

字符串缓冲区,所有存储的元素都被转成字符串,而且最后拼成了一个大的字符串。
长度可变,内部维护了一个数组,有自动扩展数组的功能。


构造器(以StringBuilder为例)

StringBuilder()

StringBuilder(Stringstr)


方法(以StringBuilder为例)

1.尾部添加(支持所有基本数据类型和有toString()方法的类)

StringBufferappend(content)

2.删除子串

StringBuilderdelete(intstart,intend)

StringBuilderdeleteCharAt(intindex)

3.获取指定字符或字符串的位置

intindexOf(Stringstr)

intindexOf(Stringstr,intfromIndex)

4.获取指定位置上的字符

charcharAt(intindex)

5.插入(支持所有基本数据类型、字符数组和有toString()方法的类)

StringBuilderinsert(intoffset,content)

6.逆序

StringBuilderreverse()

7.修改

voidsetCharAt(intindex,charch)

voidsetLength(intnewLength)

StringBuilderreplace(intstart,intend,Stringstr)

8.获取字符串

StringtoString()


示例

//创建字符串缓冲区
StringBuilderbuffer=newStringBuilder();
//1.添加数据
buffer.append(true).append("HelloJava").append(3.14);//"trueHelloJava3.14"
//2.删除数据
buffer.delete(5,11);//"trueJava3.14"
//3.获取指定字符或字符串的位置
intindex=buffer.indexOf("Java");//5
//4.获取指定位置上的字符
charch=buffer.charAt(5);//'J'
//5.插入数据
buffer.insert(4,"Hi");//"trueHiJava3.14"
//6.逆序
buffer.reverse();//"41.3avaJiHeurt"
//7.替换数据
buffer.replace(0,buffer.length(),"HelloJava");//"HelloJava"
//8.修改长度
buffer.setLength(5);//"Hello"
System.out.println(buffer.toString());
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: