八(一)、常用类之String、StringBuffer、StringBuilder

 

一、String类:

字符串,使用一对“”引起来;

1.String 声明为final 不可被继承;

2.实现了

  • Seriablizable:表示字符串是支持序列化的;
  • Compareble :可比较大小
  • CharSequence接口:提供对多种不同类型的统一只读访问 序列。

3.String内部声明了final char[] value数组,用于存储char 数组;

4.String:代表不可变的字符序列;简称:不可变性;

  • 体现1:当对字符串重新赋值时,需要重新制定内存区域赋值,不能使用原有的value进行赋值
  • 体现2:当对现有的字符串进行连接操作时,也需要重新指定内存区域赋值,不能使用原有的value值进行赋值
  • 体现3.当调用replace方法时,也需要重新指定内存区域赋值,不能使用原有的value值进行赋值

说明:

 1     @Test
 2     public void test1() {
 3         String s1 = "abc";// 自面量方式创建
 4         String s2 = s1;
 5         System.out.println(s1 == s2);
 6         s1 = "hello";
 7         System.out.println(s1 == s2);
 8         System.out.println(s1);
 9         System.out.println(s2);

19     }

这里 第一个 System.out.println(s1 == s2);这里是true;

 

s1 = "hello";
System.out.println(s1 == s2);

这里是false,因为s1就是hello,s2还是abc,这里区别于其他引用类型对象的赋值;也就是当对字符串重新赋值时,需要重新制定内存区域赋值,不能使用原有的value进行赋值

1 @Test
2     public void test4() {
3         String s1 = "abcdef";
4         String s2 = "abc";
5         s2 += "def";// abcdef
6         System.out.println("s1:" + s1);
7         System.out.println("s2:" + s2);
8         System.out.println(s1 == s2);
9     }

s1:abcdef;

s2:abcdef;

s1== s2的结果是false

体现了当对现有的字符串进行连接操作时,也需要重新指定内存区域赋值,不能使用原有的value值进行赋值;

1 @Test
2     public void test4() {
3         String s4 = "abc";
4         String s5 = s4.replace("a", "m");
5         System.out.println("s4:" + s4);
6         System.out.println("s5:" + s5);
7     }

s4:abc

s5:mbc

体现了当调用replace方法时,也需要重新指定内存区域赋值,不能使用原有的value值进行赋值

 

二、String 创建的方式

1.通过new+构造器的方式

说明:

给一个字符串赋值,此时的字符串声明在方法区的字符串常量池中;

问:String s = new String("abc");方式创建对象,在内存中创建了几个对象

答:一个是堆空间的new 对象,另一个 char 数组 对应常量池中的数据

1  String s = new String("0");
2  for(int i=0;i<=5;i++){
3  s+=i;
4  }
5  System.out.println(s)

内存解析:

再看一个例子:

@Test
    public void test2() {

        String s1 = "ABC";// 在方法区 中的 字符串常量池中
        String s2 = "ABC";// 在方法区 中的 字符串常量池中
        String s3 = new String("ABC");// 在 堆空间中
        String s4 = new String("ABC");// 在 堆空间中
        System.out.println(s1 == s2);// true
        System.out.println(s3 == s4);// false;
        System.out.println(s1 == s4);// false;
        Person p1 = new Person("Tom",1);
        Person p2 = new Person("Tom",1);
        System.out.println(p1.getName() == p2.getName());
        System.out.println(p1.getAge() == p2.getAge());
    }
 1 class Person {
 2     private String name;
 3     private int age;
 4 
 5     public String getName() {
 6         return name;
 7     }
 8 
 9     public void setName(String name) {
10         this.name = name;
11     }
12 
13     public int getAge() {
14         return age;
15     }
16 
17     public void setAge(int age) {
18         this.age = age;
19     }
20 
21     public Person(String name, int age) {
22         super();
23         this.name = name;
24         this.age = age;
25     }
26 
27 }
View Code

2.通过字面量方式(区别于new)

说明:

通过字面量方式给一个字符串赋值,此时的字符串声明在方法区的字符串常量池中;

注意:字符串常量池中不保存相同内容的字符串;也就是String的不可变性;

1  String s = "0";
2  for(int i=0;i<=5;i++){
3  s+=i;
4  }
5  System.out.println(s)

三、字符串的特性:

常量与常量的拼接结果在常量池;而且常量池中不会存在相同内容的常量;
字符串拼接:只要其中一个是变量,结果就在堆中;如果拼接的结果调用 intern(),返回值就在常量池中

 1 @Test
 2     public void test3() {
 3         String s1 = "javaEE";
 4         String s2 = "hadoop";
 5         String s3 = "javaEEhadoop";
 6         String s4 = "javaEE"+"hadoop";
 7         String s5 = s1 +"hadoop";
 8         String s6 = "javaEE"+s2;
 9         String s7 = s1+s2;
10         String s8 = s7.intern();
11         System.out.println(s3 == s4);
12         System.out.println(s3 == s5);
13         System.out.println(s3 == s6);
14         System.out.println(s5 == s6);
15         System.out.println(s3 == s8);
16         final String s9 = "hadoop";
17         String s10 = "javaEE"+s9;
18         System.out.println(s3 == s10);//这里 s9是常量
19         
20         
21         
22     }

s3 == s4:结果是true

s3 == s5:结果是false;

s3 == s6:结果是false;

s5 == s6:结果是false;

s3 == s8:结果是true

s3 == s10这里也是true

原因就是我们这里的特性;

 

 五、String的常用方法:

  1. int length():返回字符串长度;(从1开始数的,如 Helloworld,那么length 就是10)

  2. char charAt(int index):返回某索引处的字符串 return value[index]; (index 从0开始

  3. boolean isEmpty():判断空字符串 return value.length == 0;

  4. String toLowerCase():使用默认语言环境,将String中的所有字符串转化为小写

  5. String toUpperCase():使用默认语言环境,将String中的所有字符串转化为大写

  6.  String trim():去除字符串 首尾的空格;

  7. boolean equals(Object obj)比较字符串内容是否相同

  8. boolean equalsIgnoreCase(String anOtherString)与equals方法类似,忽略大小写比较字符串内容是否相同

  9. String Concat(String str):将指定字符串连接到此字符串的结尾,等价于 “+”

  10. int compareTo(String anotherString),比较两个字符串的大小;

  11. String subString(int beginIndex):返回一个新的字符串,他是此字符串的重beginindex 开始截取

  12. String subString(int beginIndex,int endIndex):返回一个新的字符串,他是此字符串的重beginindex 开始截取 endIndex结束的[beginIndex,endIndex) beginIndex从0开始算的

  13. boolean endsWith(String suffix):测试字符串是否以指定的后缀结束

  14. boolean startWith(String prefix):测试此字符串是否以指定的前缀开始;

  15. boolean startWith(string prefix,int toffset)测试此字符串从指定索引开始的子字符串是否以指定的前缀开始

  16. boolean contains(charSequence s):当且仅当此字符串包含指定的char值序列时,返回true;

  17. int indexOf(String str):返回指定子字符串在此字符串中第一次出现的索引,如果存在,则从0开始的,如果不存在,则是-1;

  18. int indexOf(String str,int fromIndex);返回指定字符串在此字符串中第一次出现的索引

  19. int lastIndexOf(String str,int fromIndex);返回指定字符串在此字符串中最右边出现的索引

  20. int lastIndexOf(String str,int fromIndex);返回指定字符串在此字符串中最右边出现的索引

  21. 注意:indexOf 和 lastIndexOf方法如果未找到,都是返回-1

  22. String replace(char oldChar,char newChar):返回一个新的字符串,他是通过newChar替换此字符串中出现的国有oldChar;

  23. String replace(charSequence target,charSequence replacement):使用指定的字面值替换此字符所有匹配字面值目标序列的子字符串

  24. String replaceAll(String regex,String replacement):使用给定的replacement替换此字符串所有匹配给定的正则表达式的子字符串

  25. String replaceFirst(String regex,String replacement):使用给定的replacement替换此字符串所有匹配给定的正则表达式的第一个子字符串

  26. boolean matches(String regex):告知此字符串是否匹配给定的正则表达式

  27. String[] split(string regex);根据给定正则表达式的匹配拆分此字符串;

  28. String[] split(string regex,int limit);根据给定正则表达式的匹配拆分此字符串;最多不超过limit个,如果超过了,剩下的全部都放到最后一个元素中

  29. String format(String format, Object... args);字符串拼接;eg:static String str = "%s和%s的%s.一刻也不能%s,无论%s走到那里,都留下一首赞歌"; 

  1 @Test
  2     public void test1() {
  3         String s1 = "Helloworld";
  4         String testNull = null;
  5         String testEmpty = "";
  6         System.out.println(s1.length());//获取数组长度
  7         System.out.println(s1.charAt(0));//获取指定位置的字符
  8         System.out.println(s1.isEmpty());//判断字符串是否为空
  9 ///        System.out.println(testNull.isEmpty());//报错
 10         System.out.println(testEmpty.isEmpty());//判断字符串是否为空
 11         System.out.println(s1.toUpperCase());//转换为大写
 12         System.out.println(s1);//Helloworld 体现了不可变性
 13         System.out.println(s1.toLowerCase());//转换为小写
 14         
 15         String s2 = " Hello    World  ";
 16         String s3 = s2.trim();//去除字符串首尾的空格
 17         System.out.println("----"+s2+"------");//体现了不可变性
 18         System.out.println("----"+s3+"------");
 19         
 20         String s4 = "HELLOWORLD";
 21         System.out.println(s1.equals(s4));
 22         System.out.println(s1.equalsIgnoreCase(s4));//忽略大小写比较字符串内容
 23         
 24         String s5 = "abc";
 25         System.out.println(s5.concat("efg"));//拼接字符串
 26         
 27         String s6 = "abf";
 28         System.out.println(s5.compareTo(s6));//涉及到字符串排序
 29         
 30         System.out.println(s6);
 31         System.out.println(s6.substring(1));
 32         System.out.println(s1.substring(2,5));//左闭右开 从2开始 到5结束 不包括5
 33         
 34         boolean str1 = s1.endsWith("rld");
 35         System.out.println(str1);
 36         
 37         boolean str2 = s1.startsWith("he");
 38         System.out.println(str2);
 39         
 40         boolean str3 = s1.startsWith("He");
 41         System.out.println(str3);
 42         
 43 
 44         boolean str4 = s1.startsWith("He",0);
 45         System.out.println(str4);
 46         
 47         boolean str5 = s1.startsWith("el",1);
 48         System.out.println(str5);
 49         
 50         boolean str6 = s1.contains("w");
 51         System.out.println(str6);
 52         
 53         int str7 = s1.indexOf("lo");
 54         System.out.println(str7);
 55         
 56         int str8 = s1.indexOf("lol");
 57         System.out.println(str8);
 58         
 59         int str9 = s1.indexOf("lo",5);
 60         System.out.println(str9);
 61         
 62         int str10 = s1.lastIndexOf("lo",5);
 63         System.out.println(str10);
 64         
 65         int str11 = s1.lastIndexOf("w");
 66         System.out.println(str11);
 67     }
 68 
 69     @Test
 70     public void test2() {
 71         String str1 = "Hello World";
 72         String str2 = str1.replace("Hello", "Byby");
 73         System.out.println(str1);
 74         System.out.println(str2);
 75         String str3 = str1.replace('H', 'B');
 76         System.out.println(str3);
 77         
 78         String str = "12hello34world5java789mysql456";
 79         String string = str.replaceAll("\\d+", ",").replaceAll("^,|,$", "");//\\d匹配数字, +表示有多个数字,^,|,$ 开头或者结尾有逗号
 80         System.out.println(string);
 81         
 82         str = "12345";
 83         boolean matches = str.matches("\\d+");
 84         System.out.println(matches);
 85         String tel = "0571-4534289";
 86         boolean result = tel.matches("0571-\\d{7,8}");//0571开头 ,数字是7-8位
 87         System.out.println(result);
 88         
 89         
 90         str = "HELLO|WORLD|JAVA";
 91         String[] strs = str.split("\\|");
 92         for(int i = 0;i<strs.length;i++) {
 93             System.out.println(strs[i]);
 94         }
 95         str2 = "hellow.world.java";
 96         String[] strs2 = str2.split("\\.");
 97         for(int i = 0;i<strs2.length;i++) {
 98             System.out.println(strs2[i]);
 99         }
100         
101 
102     }
View Code

 

1 static String str = "%s和%s的%s.一刻也不能%s,无论%s走到那里,都留下一首赞歌";
2 public static void main(String[] args) {
3    String format = String.format(str, "我", "我", "祖国", "分隔", "我","啦啦啦的马蒂");          System.out.println(format);          //输出结果:我和我的祖国.一刻也不能分隔,无论我走到那里,都留下一首赞歌
4     }

 

★★★相关面试题:

 1 package commonmethod;
 2 
 3 public class Day20StringInterviewTest9 {
 4 
 5     String str = new String("good"); 
7
char[] ch = {'t','e','s','t'}; 8 public void change(String str,char ch[]) { 9 str = "test ok";

11 ch[0] = 'b'; 12 } 13 public static void main(String[] args) { 14 Day20StringInterviewTest9 ex = new Day20StringInterviewTest9(); 15 ex.change(ex.str, ex.ch); 16 System.out.println(ex.str);18 System.out.println(ex.ch); 19 20 } 21 22 }

这里的输出结果 :

good
best

对于这个结果,前两个解释一下;想看ex.str为什么结果还是good呢?

首先需要两个知识点:

①在对象的方法中,值传递的规则是:如果形参是基本数据类型时,方法参数传递的是参数本事的值,如果参数是引用数据类型时,那个参数传递的是地址值(不是对象本身);(以下内存解析中0X开头的部分);

②String 值的不可变性;

ex.change(ex.str, ex.ch);==》形参:ex.str,其实是0x002;

str = "test ok";赋值一个新的值;常量池中没有 “test ok”,那么常量池中创建一个value值是 “test ok”的对象(这个原则,就是String不可变性的体现(即体现1));此时在该方法中产生一个 str的副本,该str副本这里称 strx吧;strx 指向test ok ;最后方法结束自动销毁(由jvm垃圾回收);最后打印出ex.str,就是打印传入的对应地址值的value值即:good;

这里的ch就是普通的引用类型变量;如果要做扩展,那么他可以换成某个对象,那么结果是什么呢?

附上内存解析图:(参考文章https://zhuanlan.zhihu.com/p/266885142

ex 实例化    

change 中的两个 str 和 ch 执行赋值操作    change方法结束 jvm垃圾回收

这里补充例子:

 1     public static String changeString(String str){
 2         return str+"ABC";
 3     }
 4     public static int changInt(int a){
 5         a = 0;
 6         return a;
 7     }
 8     @Test
 9     public void testString1() {
10         String str1="abc123";
11         int a = 23;
12         System.out.println(str1);
13         System.out.println(changInt(a));
14         System.out.println(a);
15     }

这里的结果是 ?

 abc123

abc123ABC

23

 System.out.println(str1):这个还是跟上面那个套路是一样的;
System.out.println(a);是23原因是在ChangeInt方法中 a 其实是 a·,它在方法结束后自动销毁了;所以最后a仍然是 23;

六、String的转换:

1.String与基本数据类型的转换:

    String-->基本数据类型、包装类:调用包装类的静态方法;parstXXX(str);
    基本数据类型、包装类--》string 调用S挺重载的valueOf(xxx);

1     @Test
2     public void test1() {
3         String str1 = "123";
4         int num = Integer.parseInt(str1);
5         String str2 = String.valueOf(num);
6         String str3 = num+"";
7         System.out.println(str2);
8         System.out.println(str3 == str1);
9     }

2.String 其他数据机构的转换

string 与char数组的转换 调用string toCharArray方法
string 与byte数组的转换 调用string getBytes方法
编码:String-->byte[]:调用string getBytes方法
解码:byte[]-->string:调用String的构造器;
 说明:解码时,要求解码使用的字符集必须与编码时使用的字符集一致,否则会出现乱码

 1     @Test
 2     public void test1() throws UnsupportedEncodingException {
 3         String str1 = "abc123中国";//题目 把 abc123 变成 a321cb,那么就需要变成字符串再反转;
 4         char[] charStr = str1.toCharArray();
 5         for(int i=0;i<charStr.length;i++) {
 6             System.out.println(charStr[i]);
 7         }
 8         
 9         char[] arr = new char[] {'h','e','l','l'};
10         String str2 = new String(arr);
11         System.out.println(str2);
12         System.out.println(arr);
13         System.out.println(Arrays.toString(arr));
14         byte[] toByteArr = str1.getBytes();//可以设置编码
15         for(int i=0;i<toByteArr.length;i++) {
16             System.out.println(toByteArr[i]);
17         }
18         System.out.println(toByteArr);
19         System.out.println(Arrays.toString(toByteArr));
20         byte[] toByteArr1 = str1.getBytes("gbk");//可以设置编码
21         System.out.println(Arrays.toString(toByteArr1));
22         
23         String str3 = new String(toByteArr1);//设置解码
24         System.out.println(str3);
25         
26         String str4 = new String(toByteArr1,"gbk");//解码没有出现乱码。原因是:编码集和节目集一致
27         System.out.println(str4);
28     }
View Code

 七、String、StringBuilder 、StringBuffer

 1.String、StringBuilder 、StringBuffer的区别

String:不可变的字符序列 底层使用char[]存放数据;
 StringBuffer:可变的字符序列,线程安全,效率低;底层使用char[]存放数据;
 StringBuilder:可变的字符序列,线程不安全,效率高;底层使用char[]存放数据;
 源码分析
 String str = new String()//new char[0];
 String str1 = new String("abc")//new char[]{'a','b','c'}
 
 StringBuffer sb1 = new StringBuffer();//new char[16];
 StringBuffer sb1 = new StringBuffer("abc");//new char[19]; value[0] = 'a',value[1] = 'b',value[2] = 'c'
 问题1.System.out.println(sb1.length)//3
 问题2,扩容问题,若果要添加的数据底层数组承载不了,那就需要扩容底层数组;把原来的数组复制到新的value数组;默认情况下扩容为原来容量的2倍+2(详情可参考源码)
 
 指导建议:开发中建议大家使用 StringBuilder(int capacity) 或者StringBuffer(int capacity)

2.String 转换成 StringBuilder 、StringBuffe

StringBuffer sb = new StringBuffer("aaa");

StringBulider sb = new StringBulider("aaa");

String str = new String(sb);

or

String str = sb.toString();

3.StringBuffer的常用方法:

StringBuffer append(xxx):提供了很多append方法,用于字符串拼接
  StringBufferdelete(int start,int end)删除指定位置的内容(左闭右开)
  StringBuffer replace(int start,int end,String str)把[start,end)位置替换为
  StringBuffer insert(int offset,xxx),在指定位置插入XXX
 reverse(),把当前字符串倒叙
 public int indexOf(String str)
 public String subString(int start,int end)
 public int length();
 public char charAt(int n)
 public void setCharAt(int n,char ch);
 总结:
 增:append()
 删:delete(int start,int end)
 改:public void setCharAt(int n,char ch);/StringBuffer replace(int start,int end,String str)
 查:public int indexOf(String str)
 插:StringBuffer insert(int offset,xxx)
 长度length();

 1     @Test
 2     public void test1()  {
 3         StringBuffer sb1 = new StringBuffer();
 4         sb1.append(1);
 5         sb1.append("1");
 6         System.out.println(sb1.toString());
 7         sb1.delete(0, 1);
 8         System.out.println(sb1.toString());
 9         sb1.insert(0, "112123");
10         System.out.println(sb1.replace(0, 2, "AA"));
11         System.out.println(sb1.toString());
12         sb1.insert(0, false);
13         System.out.println(sb1.toString());
14         System.out.println(sb1.reverse());
15         System.out.println(sb1.length());
16         System.out.println(sb1.indexOf("eslaf"));
17         System.out.println(sb1.charAt(10));
18          sb1.setCharAt(10, 'x');
19         System.out.println(sb1.toString());
20     }
View Code

 补充面试题:

1.字符串反转:abcdefg==>abfedcg

1     public void testInterview1() {
2         String str = "abcdefg";
3         String str1 = str.substring(0,2);
4         String str2 = str.substring(2,6);
5         String str3 = str.substring(6);
6         StringBuffer sb = new StringBuffer(str2);
7         String res = str1+sb.reverse()+str3;
8         System.out.println("字符串反转:"+res);    
9     }
View Code


2.abkkcadkabfkabkskab 问,ab一共出现过几次?

 1 @Test
 2     public void testInterview2() {
 3         String str = "abkkcadkabfkabkskab";
 4         int count = 0;
 5         int index = -1;
 6         for(int i=0;i<str.length();i++) {
 7             if(i == 0) {
 8                 index = str.indexOf("ab",0);
 9             }else {
10                 index = str.indexOf("ab",index+1);
11             }
12             
13             
14             if(index >-1) {
15                 count = count+1;
16                 
17             }else {
18                 break;
19             }
20         }
21         System.out.println(str.length());
22         System.out.println(count);
23         
24     }
View Code


3.获取两个字符串中的最大相同子串;str1 = "abcwerthelloyuiodef";str2 = "cvhellobnm";

 1 @Test
 2     public void testInterviwq3() {
 3         String str1 = "abcwerthelloyuiodefn";
 4         String str2 = "cvhellodefnm";
 5         String min = "";
 6         String max = "";
 7         StringBuffer sb = new StringBuffer();
 8         if(str1.length()<= str2.length()) {
 9             min = str1;
10             max = str2;
11         }else {
12             min = str2;
13             max = str1;
14         }
15         for(int i=0;i<min.length();i++) {
16             for(int x=0,y=min.length()-i;y<=min.length();x++,y++) {
17                 String tem = min.substring(x,y);
18                 System.out.println(tem);
19                 if(max.contains(tem)) {
20                     sb.append(tem+"|");
21                 }
22             }
23             if(sb.length()>1) {
24                 break;
25             }
26         }
27         System.out.println("最大相同子串:"+sb.toString());
28     }
View Code

4.StringBuffer中注意的一个地方:

 1 @Test
 2     public void testInterview4() {
 3         String str = null;
 4         StringBuffer sb = new StringBuffer();
 5         sb.append(str);//appendNull方法把 ‘null’ append进去了;
 6         System.out.println(sb.length());
 7         StringBuffer sb2 = new StringBuffer(str);//这里有一个 str.length;这里str是null,所以报错
 8         System.out.println(sb.length());
 9         
10     }

 

posted @ 2021-02-18 11:57  啄木鸟伍迪  阅读(73)  评论(0编辑  收藏  举报
//火箭 GenerateContentList();