zoukankan      html  css  js  c++  java
  • 八(一)、常用类之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():返回字符串长度;
    2. char charAt(int index):返回某索引处的字符串 return value[index];
    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结束的
    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):返回指定子字符串在此字符串中第一次出现的索引
    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个,如果超过了,剩下的全部都放到最后一个元素中
      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 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     }
    我从来不相信什么懒洋洋的自由。我向往的自由是通过勤奋和努力实现的更广阔的人生。 我要做一个自由又自律的人,靠势必实现的决心认真地活着。
  • 相关阅读:
    RPC框架实践之:Apache Thrift
    ubuntu中安装hadoop集群
    前端开发浏览器兼容问题
    3亿(int)数据-2亿(int)数据 求差集
    mvn docker 部署 每次都需要下载包的问题
    树莓派操作记录
    mysql 实现类似开窗函数的功能
    mysql 多字段更新
    go proxy转发工作中碰到的问题
    之前项目使用的轻量的goweb框架
  • 原文地址:https://www.cnblogs.com/lixiuming521125/p/14404125.html
Copyright © 2011-2022 走看看