黑马程序员——String、StringBuffer、StringBuilder和基本数据类型包装类

时间:2022-06-28 04:00:09

------Java培训、Android培训、iOS培训、.Net培训、期待与您交流! -------


 

第一部分、String、StringBuffer、StringBuilder

一、String类 

1、概述

String类型的特点:字符串对象一旦被初始化就不会被改变。

  String s=“abc”;s=“nba”;

  "abc"字符串对象并没有被改变,只是引用变量s指向了新创建的字符串对象"nba"。

Java中String是一个特殊的包装类数据有两种创建形式:

  1. String s1 = "abc";
  2. String s2 = new String("abc");    

    第一种先在栈中创建一个对String类的对象引用变量s,然后去查找"abc"是否被保存在字符串常量池中,如果没有则在栈中创建三个char型的值'a'、'b'、'c',然后在堆中创建一个String对象object,它的值是刚才在栈中创建的三个char型值组成的数组{'a'、'b'、'c'},接着这个String对象object被存放进字符串常量池,最后将s指向这个对象的地址,如果"abc"已经被保存在字符串常量池中,则在字符串常量池中找到值为"abc"的对象object,然后将s指向这个对象的地址。

    第一种特点:JVM会自动根据栈中数据的实际情况来决定是否有必要创建新对象。

    第二种可以分解成两步1、String object = "abc"; 2、String s = new String(object); 第一步参考第一种创建方式,而第二步由于"abc"已经被创建并保存到字符串常量池中,因此jvm只会在堆中新创建一个String对象,它的值共享栈中已有的三个char型值。

    第二种特点:一概在堆中创建新对象,而不管其字符串值是否相等,是否有必要创建新对象。所以这里的s1!=s2。

 String类复写了Object中的equals方法,建立了String类自己的判断字符串对象是否相同的依据。只比较字符串内容,不比较地址。所以s1.equals(s2)为真。

2、构造函数

  第一类:public String(byte[] bytes) 通过字节数组构造一个字符串对象。

  第二类:public String(char[] value) 通过字符数组构造一个字符串对象。

  详细的构造函数可以参考API的说明:

  黑马程序员——String、StringBuffer、StringBuilder和基本数据类型包装类

3、String类常见方法介绍

  第一类获取:

  int length();获取字符串中字符的个数(长度)

  char charAt(int index);根据位置获取字符

  int indexOf(int ch);根据字符获取在字符串中的位置。indexO方法参数f类型为int是为了既可以支持字符,也可以支持字符在ASCII码中对应的数字。

  int indexOf(int ch,int fromIndex);从指定位置开始查找ch第一次出现的位置。

  int lastIndexOf(int ch);根据字符串获取在字符串中第一次出现的位置。找不到返回-1.

  

  String substring(int beginIndex,int endIndex);获取字符串中的一部分字符串,也叫子串。

  String substring(int beginIndex);

  第二类转换:

  String[] split(String regex);将字符串变成字符串数组(字符串的切割)涉及到正则表达式。

  char[] toCharArray();将字符串变成字符数组。

  char[] getBytes();将字符串变成字节数组

  String toUpperCase();大写

  String toLowerCase();小写

 

  String replace(char oldCh,char newCh);将字符串中的内容进行替换,replace方法如果没有找到要替换的内容,则返回的还是原字符串。

  String replace(String s1,String s2);

 

  String trim();去除字符串两端空格

  String concat(String str);将字符串进行连接。concat效果与"+"连接符效果一致,但是效果更高一些。

  第三类判断

  boolean equals(Object obj);两个字符串内容是否相同

  boolean equalsIgnoreCase(String str);忽略大小写比较字符串内容。

  boolean contains(String str);字符串中是否包含指定字符串

  boolean startsWith(String str);字符串是否以指定字符串开头

  boolean endsWith(String str);是否以指定字符串结尾

  第四类比较

  int compareTo(String str); 如果参数字符串等于此字符串,则返回值0;如果此字符串按字典顺序小于字符串参数,则返回一个小于0的值;如果此字符串按字典顺序大于字符串参数,则返回一个大于0的值

 

  String intern();返回字符串对象的规范化表示形式,当调用intern方法时,如果池已经包含一个等于此String对象的字符串(用equals(Object)方法确定),则返回池中的字符串。否则,将此String对象添加到池中,并返回此String对象的引用。

  学了这么多的String类型的方法,下面用几个个综合应用来练习一下这些方法。

练习1、

 1 /*
 2     1、对字符串"12 5 42 32 87 -7 55 7 8"中的数字进行排序。
 3     思路:
 4         第一步将字符串转换成为字符串数组
 5         第二步将字符串数组转换成为整数数组
 6         第三步对整数数组排序,
 7         第四部把排序后的整数数组转换成为字符串
 8 */
 9 import java.util.*;
10 class  StringSort
11 {
12     public static void main(String[] args) 
13     {
14         String strSrc="12 5 42 32 87 -7 55 7 8";
15         //1、将字符串转换成为字符串数组
16         String[] strs = strToCharArray(strSrc);
17         //第二步将字符串数组转换成为整数数组,split方法
18         int[] strInts =strsToInts(strs);
19         //整数数组排序
20         mySort(strInts);
21         
22         sop("排序前字符串为:"+strSrc);
23         //把排序后的整数数组转换成为字符串
24         sop("排序前字符串为:"+intsToString(strInts));
25     }
26     public static void sop(Object obj)
27     {
28         System.out.println(obj);
29     }
30 
31     static String[] strToCharArray(String str)
32     {
33         return str.split(" ");
34     }
35 
36     static int[] strsToInts(String[] strs)
37     {
38         int[] ints=new int[strs.length];
39         for(int i=0;i<strs.length;i++)
40         {
41             ints[i]=Integer.parseInt(strs[i]);
42         }
43         return ints;
44     }
45     //排序
46     static void mySort(int[] ints)
47     {
48         for(int i=0;i<ints.length-1;i++)
49         {
50             for(int j=i+1;j<ints.length;j++)
51             {
52                 if(ints[i]>ints[j])
53                 {
54                     int temp=ints[i];
55                     ints[i]=ints[j];
56                     ints[j]=temp;
57                 }
58             }
59         }
60     }
61 
62     static String intsToString(int[] ints)
63     {
64         StringBuilder str=new StringBuilder();
65         for(int i=0;i<ints.length;i++)
66         {
67             if(i!=ints.length-1)
68                 str.append(ints[i]+" ");
69             else
70                 str.append(ints[i]);
71         }
72         return str.toString();
73     }
74 }

结果为:

  黑马程序员——String、StringBuffer、StringBuilder和基本数据类型包装类

 

练习2:

 1 /*
 2     2、一个子串nba在整串中出现的次数 "nbaernbatynbauinbaopnba"
 3         思路:indexOf获取子串在字符串中的位置,如果大于0则说明存在,小于0则说明不存在。
 4         如果找到了,就在找到的位置加上子串的长度位置开始查找,知道小于0.
 5     */
 6     public static void Excercise02()
 7     {
 8         String src = "nbaernbatynbauinbaopnba";
 9         String key = "nba";
10         int count = getKeyCount(src,key);
11         System.out.println("count: "+count);
12     }
13     public static int getKeyCount(String src,String key)
14     {
15         int count=0;
16         int fromIndex=0;
17         while((fromIndex=src.indexOf(key,fromIndex))!=-1)
18         {
19             fromIndex=fromIndex+key.length();//将查找的起始位置偏移继续查找
20             count++;
21         }
22         return count;
23     }

结果为:

  黑马程序员——String、StringBuffer、StringBuilder和基本数据类型包装类

可以看到nba在目的串中确实是出现了五次。

练习3、

 1 3、两个字符串中最大相同的子串
 2     "qwerabcdtyuiop"
 3     "xcabcdvbn"
 4     思路:
 5     ①既然取的是最大子串,先看短的那个字符串是否在长的那个字符串中。如果存在,短的那个字符串
 6 就是最大子串。
 7     ②如果不是,那么就将短的那个子串进行长度递减的方式去子串,去子串中判断是否存在。如果存在
 8 就已找到,就不用再找了
 9     */
10     public static void excercise03()
11     {
12         String s1="qwerabcdtyuiop";
13         String s2="xcabcdvbn";
14         String s=getMaxSub(s1,s2);
15         System.out.println(s1+","+s2+"的最大共同子串为: "+s);
16     }
17     public static String getMaxSub(String s1,String s2)
18     {
19         String max=null,min=null;
20         max=s1.length()>s2.length()?s1:s2;
21         min=max.equals(s1)?s2:s1;//找出两个字符串哪个长,哪个短
22         for(int i=0;i<min.length();i++)
23         {
24             for(int a=0,b=min.length()-i-1;b<min.length();a++,b++)
25             {
26                 String temp=min.substring(a,b+1);//sub方法包含头不包含尾
27                 if(max.contains(temp))
28                 {
29                     return temp;
30                 }
31             }
32         }
33         return null;
34 
35     }

运行结果为:

黑马程序员——String、StringBuffer、StringBuilder和基本数据类型包装类

最长的共同子串确实为abcd。

 

StringBuffer

  StringBuffer:就是字符串缓冲区,用于存储数据的容器。

  StringBuffer类和String一样,也用来代表字符串,只是由于StringBuffer的内部实现方式和String不同,所以StringBuffer在进行字符串处理时,不生成新的对象,在内存使用上要优于String类。所以在实际使用时,如果经常需要对一个字符串进行修改,例如插入、删除等操作,使用StringBuffer要更加适合一些。

  在StringBuffer类中存在很多和String类一样的方法,这些方法在功能上和String类中的功能是完全一样的。但是有一个最显著的区别在于,对于StringBuffer对象的每次修改都会改变对象自身,这点是和String类最大的区别。

  StringBuffer的特点:长度可变,可以存储不同类型的数据。最终要转换成为字符串进行使用。StringBuffer的字符串缓冲区初始容量为16个字符,其实质还是数组。

StringBuffer类的方法介绍:

  添加:

    StringBuffer append(data);在末尾添加

    StringBuffer insert(index,data);在指定位置添加,insert方法也可以对字符串进行修改。

  删除:

    StringBuffer delete(int start,int end);包含头,不包含尾。

    StringBuffer deleteCharAt(int index):删除指定位置的元素

  特有方法:

    void setLength(int newLength);设置字符序列的长度

    public StringBuffer reverse();将字符序列用其反转形式取代

  注意:使用setLength设置StringBuffer中字符序列的长度。如果小于已有字符序列的长度,相当于清除缓冲区中的一部分内容。如果大于已有字符序列的长度,相当于扩充缓冲区,扩充部门内容用空格字符填充。

    当创建的StringBuffer内容长度大于16,将会新创建一个新数组,长度比旧数组要长。然后把就数组的内容拷贝到新的数组,超出旧数组长度范围的内容将会放在新数组现在内容的后面,也可以通过StringBuffer(int capacity);构造函数自己设置StringBuffer缓冲区长度。

StringBuilder

   jdk1.5以后出现了功能和StringBuffer一模一样的对象,就是StringBuilder。 

  StringBuffer和StringBuilder两者的区别:

    StringBuffer是线程同步的,通常用于多线程。StringBuilder是线程不同步的,通常用于单线程,它的出现能够提高程序效率。故StringBuilder多用于多个线程是不安全的,如果需要这样的同步,可以使用StringBuffer或者自己用加同步锁。

  小知识:JDK升级的目的:简化书写,提高效率,增加安全性。

  接下来用StringBuilder做一个小练习:将一个整数数组转化为一个字符串。

 1 /*
 2         4、将一个整数数组转化为一个字符串
 3     */
 4     public static String exercise04()
 5     {
 6         int[] its={1,2,3,4,5,6,7,10};
 7         StringBuilder sb=new StringBuilder();//StringBuilder避免了String反复创建对象,提高了效率
 8         for(int i=0;i<its.length;i++)
 9         {
10             if(i!=its.length-1)
11             {
12                 sb.append(its[i]+",");//在数字中间加逗号分隔
13             }
14             else
15                 sb.append(its[i]);//最后一个数不加逗号
16         }
17         return sb.toString();
18     }

运行的结果为:  

黑马程序员——String、StringBuffer、StringBuilder和基本数据类型包装类

      

第二部分、基本数据包装类

  为了方便操作基本数据类型值,将其封装成了对象,在对象中定义了属性和行为丰富了该数据的操作。用于描述该对象的类就称为基本数据类型对象包装类。

  基本数据类型------》基本数据包装类

    byte     Byte

    short      Short

    int      Integer

    long     Long

    float     Float

    double    Double

    char     Character

    boolean   Boolean

    该包装对象主要用于基本类型和字符串之间的转换:

    基本类型--》字符串

      1. 基本类型数值+""

      2. 用String类中的静态方法valueOf(基本类型数值);

    字符串--》基本数据类型

      1. 使用包装类中的静态方法xxx parseXxx("xxx");如:int parseInt(String str);

      2. 如果字符串被Integer进行对象的封装,可使用另一个非静态的方法,intValue。将一个Integer对象转成基本数据类型值。

      3. 用Integer的静态方法valueOf(String s);

    进制转换:

    十进制-->其他进制方法:String toBinaryString(int i);等

    其他进制-->十进制方法:int parseInt(String s,int radix);

 1 public static void exercise05()
 2     {
 3         System.out.println(Integer.parseInt("123"));
 4         System.out.println(Integer.valueOf("123"));
 5         //十进制--》其它进制
 6         System.out.println(Integer.toBinaryString(60));
 7         System.out.println(Integer.toOctalString(60));
 8         System.out.println(Integer.toHexString(60));
 9         System.out.println(Integer.toString(60,2));
10         //其他进制--》十进制
11         System.out.println(Integer.parseInt("110",16));
12         System.out.println(Integer.parseInt("110",10));
13         System.out.println(Integer.parseInt("110",8));
14         System.out.println(Integer.parseInt("110",2));
15     }

运行结果为:

黑马程序员——String、StringBuffer、StringBuilder和基本数据类型包装类

  本次内容总结到这里就完了,字符串这个特殊的类对象,需要非常熟悉类中的各种方法,在编程时就能显著的提高程序的运行效率。内容上字符串的特性需要从原理上理解,更多的是需要记忆和练习String类中的各种方法。