String类的特点:字符串对象一旦被初始化就不会被改变。
public static void main(String[] args) {
String s ="abc";
s="nba";
System.out.println("s="+s);//s=nba
}
原因分析:
"abc"字符串对象并没有被改变,只是引用变量s指向了新创建的字符串对象"nba"。
public static void main(String[] args) {
String s1 ="abc";
String s2 ="abc";
System.out.println(s1==s2);//true
}
原因分析:
字符串创建的时候,有一个字符串常量池,s1创建后,"abc"放入其中。
s2创建的时候,"abc"已经存在于字符串常量池中,故引用变量s2直接指向了已经存在的"abc"字符串对象,故s1==s2。
public static void main(String[] args) {
String s1 ="abc";
String s2 =new String("abc" );
System.out.println(s1==s2);//false
}
原因分析:
s1创建后,是在字符串常量池中创建了一个"abc"字符串对象。
而s2是在堆内存中创建了另外一个"abc"字符串对象。所以,两个对象不是同一个对象。
public static void main(String[] args) {
String s1 ="abc";
String s2 =new String("abc" );
System.out.println(s1.equals(s2));//true
}
原因分析:
String类复写了Object中的equals方法,建立了String类自己的判断字符串对象是否相同的依据。
只比较字符串内容,不比较地址。equals方法
String类的构造函数
构造函数:String(byte[] bytes)
示例1:
String s=new String();//等效于String s = "";不等效于String s = null;
public static void main(String[] args) {
String s = new String();
System.out.println(s=="");//false
System.out.println(s.equals(""));//true
byte[] arr = {65,66,67,68};
String s1 = new String(arr);
System.out.println(s1);//ABCD
}
构造函数:String(char[] chr)
public static void main(String[] args) {
char[] arr = {'j','a','v','a'};
String s1 = new String(arr);
System.out.println(s1);//java
}
构造函数:String(char[] value,int offset位移位数,int count取的个数)
从下标为offset取的个数是count
public static void main(String[] args) {
char[] arr = {'j','a','v','a'};
String s1 = new String(arr,1,2);
System.out.println(s1);//av
}
String类部分方法
1、获取
int length(); 获取字符串中字符的个数(长度)
示例1:
public static void main(String[] args) {
String s = new String("abcde" );
System.out.println( "len = " + s.length());//5
}
char charAt(int index);根据位置获取字符
public static void main(String[] args) {
String s = new String("abcde" );
System.out.println( "char:" + s.charAt(2));//char:c
}
int indexOf(int ch);根据字符获取在字符串中的位置
indexOf方法参数f类型为int是为了既可以支持字符,也可以支持字符在ASCII码中对应的数字。
从指定位置开始查找ch第一次出现的位置。
int indexOf(int ch,int fromIndex);
int indexOf(String str);
intindexOf(String str,int fromIndex);
根据字符串获取在字符串中最后一次出现的位置。
int lastIndexOf(int ch);
int lastIndexOf(int ch,int fromIndex);
int lastIndexOf(String str);
intlastIndexOf(String str,int fromIndex);
public static void main(String[] args) {
String s = new String("abcdea");
System.out.println("index:" + s.indexOf('a'));//index:0
System.out.println("index:" + s.indexOf('k'));//index:-1
System.out.println("lastIndex:" + s.lastIndexOf('a'));//lastIndex:5
}
P.S.
可以根据-1,来判断该字符或者字符串是否存在。
获取字符串中的一部分字符串,也叫子串。
String substring(intbeginIndex,int endIndex);即str.substring(2,5).从位置2开始获取字符到位置5结束。
String substring(int beginIndex);
public static void main(String[] args) {
String s = new String("abcdea");
System.out.println( "substring:" + s.substring(2));//substring:cdea
System.out.println( "substring:" + s.substring(2,4));//substring:cd
}
2、转换
将字符串变成字符串数组(字符串的切割)
String[] split(String regex以此为分割点);涉及到正则表达式。
示例5:
public static void main(String[] args) {
String s = "张三,李四,王五" ;
String[] arr = s.split( ",");
for (int i = 0; i < arr.length; i++) {
System.out.printf(arr[i]);
}
//张三李四王五
}
示例6:
public static void main(String[] args) {
String s = "张三.李四.王五";
String[] arr = s.split("\\.");
for (int i = 0; i < arr.length; i++) {
System.out.printf(arr[i]);
}
//张三李四王五
}
P.S.
将字符串变成字符数组
char[] toCharArray();
示例7:
String s = "abc";
char[] chs = s.toCharArray();
for (int i = 0; i < chs.length; i++) {
System.out.print(chs[i]);//abc
}
将字符串变成字节数组
char[] getBytes();
示例8:
String s = "ab" ;
byte[] bytes = s.getBytes();
for (int i = 0; i < bytes.length; i++) {
System.out.print(bytes[i]);
}
//9798
//打印ASCII码对应的数字。
将字符串中的字母转成大小写 String toUpperCase();大写
String toLowerCase();小写
示例9:
System.out.println( "Abc".toUpperCase());//ABC
将字符串中的内容进行替换 Stringreplace(charoldCh,char newCh);
String replace(Strings1,String s2);
String s1 = "java";
String s2 = s1.replace( 'a','o' );
String s3 = s1.replace( 'q','o' );
System.out.println(s2);//jovo
System.out.println(s3);//java
System.out.println(s1 == s3);//true
P.S.
replace方法如果没有找到要替换的内容,则返回的还是原字符串。
去除字符串两端空格 String trim();
System.out.println( "-" + " abc c " .trim() + "-");
运行结果:-abc c-
将字符串进行连接 String concat(String str);
示例12:
System.out.println( "abc".concat("kk" ));//abckk
System.out.println( "abc" + "kk" );//abckk
P.S.
concat效果与"+"连接符效果一致,但是效果更高一些。
将其他类型数据转换成字符串
示例13:
System.out.println(String.valueOf(4) + 1);//41
System.out.println( "" + 4 + 1);//41
3、判断两个字符串内容是否相同呢?boolean equals(Object obj);
boolean equalsIgnoreCase(String str);忽略大小写比较字符串内容
示例14:
System.out.println("abc".equalsIgnoreCase( "ABC"));//true
字符串中是否包含指定字符串boolean contains(String str);
示例15:
System.out.println("abc".contains( "bc"));//true
3.3字符串是否以指定字符串开头 boolean startsWith(String str);
是否以指定字符串结尾 boolean endsWith(String str);
示例16:
String str = "ArrayDemo.java";
System.out.println(str.startsWith( "Array"));//true
System.out.println(str.endsWith( "java"));//true
4、比较
int compareTo(String str);比较的字符串不相等,返回两个字符之间字典顺序之差。
如果参数字符串等于此字符串,则返回值0;如果此字符串按字典顺序小于字符串参数,则返回一个小于0的值;如果此字符串按字典顺序大于字符串参数,则返回一个大于0的值。
示例17:
System. out.println("a" .compareTo("A"));//32
char c ='A'+32;
System.out.println(c);//a
运行结果:
字典顺序排序中,a=A+32;故输出的是32
示例18:
System.out.println("abc".compareTo("aqz"));//-15
System.out.println('b' - 'q');//-15
运行结果:-15
P.S "abc"和"aqz"两个字符串比较,'a'和'a'相等,'b' - 'q' = -15,'c'和'z'也就没有必要比较。
5、返回字符串对象的规范化表示形式
String intern();当没有内容相同的字符串在池中,将该对象添加到池中,返回引用
当调用intern方法时,如果池已经包含一个等于(内容相等)此String对象的字符串(用equals(Object)方法确定),则返回池中的字符串。否则,将此String对象添加到池中,并返回此String对象的引用。
示例19:
String s1 = new String("abc");
String s2 = s1.intern();
System.out.println(s1 == s2);//false
运行结果:false
s1对象并不是在池中创建对象。而是在堆内存中。故不相等。
练习
{"nba","abc","cba","zz","qq","haha"}
思路:
①对数组排序,可以用选择,冒泡都行。
②for嵌套、比较以及换位。
③使用String类中提供的用于字符串比较的功能进行比较。
代码:
public static void main(String[] args) {
String[] arr = {"nba", "abc", "cba", "zz", "qq", "haha"};
bubbleSort(arr);
for (int i = 0; i < arr.length; i++) {
System.out.print(arr[i] + ",");
}
//abc,cba,haha,nba,qq,zz,
}
//冒泡排序法
public static void bubbleSort(String[] arr) {
for (int x = 0; x < arr.length - 1; x++) {
for (int y = x + 1; y < arr.length; y++) {
//大的值往后面冒泡
if (arr[x].compareTo(arr[y]) > 0) {
swap(arr, x, y);
}
}
}
}
public static void swap(String[] arr, int a, int b) {
String temp = arr[a];
arr[a] = arr[b];
arr[b] = temp;
}
2、一个子串"nba"在整串中出现的次数 "nbaernbatynbauinbaopnba"
思路:
①要找的子串是否存在,如果存在获取其出现的位置,这个可以使用indexOf完成。
②如果找到了,那么就记录出现的位置并在剩余的字符串中继续查找该子串,而剩余字符串的起始位是出现位置+子串的长度。
③以此类推,通过循环完成查找,如果找不到就是-1,并且每次找到用计数器记录。
代码:
public static void main(String[] args) {
String str = "nbaernbatynbauinbaopnba";
String key = "nba";
int count = getKeyStringCount(str, key);
System.out.println("count = " + count);//count = 5
}
public static int getKeyStringCount(String str, String key) {
//1、定义计数器
int count = 0;
//2、定义变量记录key出现的位置
int index = 0;
while ((index = str.indexOf(key)) != -1) {
//=先运算右边的,当子串不为-1,则存在于字符串中,并把值赋给位置。
str = str.substring(index + key.length());
//sb.substring,从”出现的位置+子串的长度”的位置,继续获取和寻找。
count++;
}
return count;
}
2、 两个字符串中最大相同的子串 "qwerabcdtyuiop"和"xcabcdvbn"
思路:
①既然取的是最大子串,先看短的那个字符串是否在长的那个字符串中。如果存在,短的那个字符串就是最大子串。
②如果不是,那么就将短的那个子串进行长度递减的方式去子串,去子串中判断是否存在。如果存在就已找到,就不用再找了。
代码:
public static void main(String[] args) {
String str = "nbaernbatynbauinbaopnba";
String key = "nbau";
String common = getMaxSubstring(str, key);
System.out.println(common);//nbau
}
public static String getMaxSubstring(String s1, String s2) {
String max = null, min = null;
//获取字符串长的给max
max = (s1.length() > s2.length()) ? s1 : s2;
//先判断两个字符串是否相同?不相同时,再获取min。减少比较的次数。
min = max.equals(s1) ? s2 : s1;
//在这里,当max=s1,不相同,min=s2.
//对短的数组进行递减比较。
//1-substring(0,2)-substring(1,3)
for (int i = 0; i < min.length(); i++) {
for (int a = 0, b = min.length() - i;
b != min.length() + 1;
a++, b++) {
//让b保证不超过字符串的长度。
String sub = min.substring(a, b);
//获取字符串,从a到b
if (max.contains(sub)) {
//contains.判断长的字符串是否包含短的字符串
return sub;
}
}
}
return null;
}
思路:
①定义两个变量。
一个变量作为从头开始判断字符串空格的角标,不断++。
一个变量作为从尾开始判断字符串空格的角标,不断--。
②判断到不是空格为止,取头部之间的字符串即可。
代码:
public static void main(String[] args) {
String s1 = " abc c ";
System.out.println(myTrim(s1));//abc c
}
public static String myTrim(String s) {
//定义头,尾
int start = 0, end = s.length() - 1;
while (start <= end && s.charAt(start) == ' ') {
//把开头的空格剔除s.charAt(start) ==’ ’
start++;
}
while (start <= end && s.charAt(end) == ' ') {
System.out.println(end);
end--;
}
return s.substring(start, end + 1);
}
StringBuffer:
就是字符串缓冲区,用于存储数据的容器。最终要转成字符串进行使用
特点:
1. 长度是可变的。
2. 可以存储不同类型数据。
3. 最终要转成字符串进行使用。
P.S.
StringBuffer的字符串缓冲区初始容量为16个字符,其实质还是数组。
StringBuffer既然是一个容器对象,应该具备什么功能呢?
StringBufferappend(data); 添加 StringBuffer insert(修改位置index,data);修改
//创建缓冲区对象
StringBuffer sb1 = new StringBuffer();
StringBuffer sb2 = sb1.append(4);
System.out.println(sb1);//4 此时sb1添加了’4’字符
System.out.println(sb2);//4
System.out.println(sb1==sb2);//true
原因分析:
sb1.append(4);语句是在缓冲区中添加4,然后将sb2引用变量指向了最终生成的字符串对象,sb1也指向这个新生成的字符串对象,故两者指向的是同一个对象。
StringBuffer sb1 = new StringBuffer();
sb1.append(4).append(5);
sb1.insert(1,"haha");
System.out.println(sb1);//4haha5
P.S.
insert方法也可以对字符串进行修改。
StringBufferdelete(int start,int end); 删除包含头,不包含尾。即头尾之间
StringBuffer deleteCharAt(int index):删除指定位置的元素。
StringBuffer sb = new StringBuffer("abcd");
sb.delete(1, 3);
System.out.println(sb);//ad
//清空缓冲区
sb.delete(0, sb.length());
System.out.println(sb);
3、查找
char charAt(int index);
int indexO(Stringstr);
intlastIndexOf(String str);
4、StringBuffer replace(int start,int end,String str); 修改。包括头,不包括尾
voidsetCharAt(int index,char ch);修改位置字符
StringBuffer sb = new StringBuffer("abcd" );
sb.replace(1,3,"---");
//包括位置1到2之间替换成---。即a---d
System.out.println(sb);//a---d
sb.setCharAt(2,'q');
System.out.println(sb);//a-q-d
5、其他方法
void setLength(int newLength);设置字符序列的长度
public StringBuffer reverse();将字符序列用其反转形式取代
StringBuffer sb = new StringBuffer("abcd" );
sb.setLength(2);
System.out.println(sb);//ab
sb.setLength(3);
sb.append("-");
System.out.println(sb);//ab -
sb.reverse();
System.out.println(sb);//- ba
P.S.
1、使用setLength设置StringBuffer中字符序列的长度。
如果小于已有字符序列的长度,相当于清除缓冲区中的一部分内容。
如果大于已有字符序列的长度,相当于扩充缓冲区,扩充部分内容用空格字符填充。
2、当创建的StringBuffer内容长度大于16,将会新创建一个新数组,长度比旧数组要长。然后把就数组的内容拷贝到新的数组,超出旧数组长度范围的内容将会放在新数组现在内容的后面,也可以通过StringBuffer(int capacity);构造函数自己设置StringBuffer缓冲区长度。
StringBuilder
jdk1.5以后出现了功能和StringBuffer一模一样的对象,就是StringBuilder。
不同的是:
StringBuffer是线程同步的,通常用于多线程。
StringBuilder是线程不同步的,通常用于单线程,它的出现能够提高程序效率。
故StringBuilder多用于多个线程是不安全的,如果需要这样的同步,则建议使用StringBuffer。
P.S.
JDK一般升级目的:
1、简化书写。
2、提高效率。
3、增加安全性。
示例:将一个int数组变成字符串。
public static void main(String[] args) {
int[] arr = {3,1,5,4,8};
String s = arrayToString(arr);
System.out.println(s);//[3,1,5,4,8]
}
public static String arrayToString(int[] arr) {
StringBuilder sb = new StringBuilder();
sb.append("[");
for (int i = 0; i < arr.length; i++) {
if (i != arr.length - 1) {
sb.append(arr[i]).append(",");
} else {
sb.append(arr[i]).append("]");
}
}
return sb.toString();
}