从此
文章
📄文章 #️⃣专题 🌐上网 📺 🛒 📱

Java String、StringBuffer 和 StringBuilder

🕗2019-08-14

Java常用类

String类

String表示字符串,所谓字符串,就是一连串的字符,是java中最常用的类之一。
String是不可变类,一旦String对象被创建,包含在对象中的字符序列(内容)是不可变的,直到对象被销毁;
String对象保存在JVM的常量池中,String类是用final来修饰的,是不可以被继承的类。

常量池

常量池: JVM中一块独立的区域存放字符串常量和基本类型常量(被public static final修饰的)。
String使用private final char value[]来实现字符串的存储,也就是说String对象创建之后
,就不能再修改此对象中存储的字符串内容,就是因为如此,才说String类型是不可变的.

String对象的创建方式

    String str = "HelloWorld";
    String str2 = new String("upuptop");
    String str3 = String.valueOf(1);
    String str4 = 123+"";

String对象比较:

单独使用""引号创建的字符串都是常量,编译期就已经确定存储到常量池中;
使用new String("")创建的对象会存储到堆内存中,是运行期新创建的;
使用只包含常量的字符串连接符如"aa" + "bb"创建的也是常量,编译期就能确定,已经确定存储到常量池中;
使用包含变量的字符串连接符如"aa" + s1创建的对象是运行期才创建的,存储在堆中;


public class StringDemo {
    public static void main(String[] args) {
        /*
         *  "" 其实表示的是  String的匿名对象
         */
        String s = "";
        /**
         * String()    初始化一个新创建的 String 对象,使其表示一个空字符序列。
         *  "",不是表示 null
         *  String(String original) 
         *  String s = new String("asd");// s 的值就是 asd
         */
        s = new String();//""
        String s1  = new String("11");
        String s2  = new String("11");
        System.out.println(s1 == s2);//false
        String s3 = "22";
        String s4 = "22";
        System.out.println(s3 == s4);//true
        System.out.println(s3 == s2);//false
        String  s5 = "2" + "2";//这句话其实在编译器编译后的class文件中 已经变成  "22"
        //s5创建了几个对象?//回答:最多一个,如果常量池里面没有就是创建一个,如果常量池里本来就有就是创建零个!下面的str一样的道理。
        String str = "A" +"B"+ "C" +"D" +"E";//String str = "ABCDE";
        System.out.println(s3 == s5);//true
        /**
         * String特点:    不可变的,  一个String对象的内容不能变,一旦内容变量该对象就变成一个新的String对象了
         *  String  str = "AAA";
         *  str = str+"12";
         */
        String str1 = "ABCDE";
        System.out.println(str == str1);//true
        String str2 = "ABC" + "DE";
        System.out.println(str == str2);//true
        String  ss = "AB";
        String str3 = ss + "CDE";//这里的str3在运行期才能确定内容值
        System.out.println(str3 == str2);//false
        String str4 = getStr() +"CDE";//在运行期才能确定 str4的值
        System.out.println(str == str4);//false
        System.out.println(str3 == str4);//false
        /*
         *  String s = "cd";    //一个String对象
            s = s + "itcast";   //itcast也是String对象, 最后的s的值cditcast,也是一个String对象
            System.out.print(s);
         * */
    }
    public static String getStr(){
        return "AB";
    }
}

String常用方法

方法名 意义
String() 初始化一个新的 String 对象,使其表示一个空字符序列,并不是返回空(不等于 null)。
String(StringBuffer buffer) 根据StringBuffer对象来创建String对象;
String(StringBuilder builder) 同上
char charAt(int index) 取字符串中指定位置的字符,index从0开始计算。
String concat(String str) 连接字符串,等同于 “+”;
boolean contentEquals(StringBuffer buffer) 若二者包含的字符序列相同时就返回true;
boolean equals(Object obj) 将该字符串与指定对象比较,若二者包含的字符序列相等返回true;
boolean equalsIgnoreCase(String anotherString) 将此 String 与另一个 String 比较,不考虑大小写;
byte[] getBytes() 将该字符串转换成byte数组;
int indexOf(String str) 找出str字符串在该字符串中第一次出现的位置;
int indexOf(String str, int fromIndex) 返回指定子字符串在此字符串中第一次出现处的索引,从指定的索引开始;
int lastIndexOf(String str) 返回指定子字符串在此字符串中最后一次出现处的索引;
int length() 返回当前字符串长度;
String replace(char oldChar, char newChar) 返回一个新的字符串,它是通过用 newChar 替换此字符串中出现的所有 oldChar 得到的。
String replaceAll(String regex, String replacement) 使用给定的 字符串replacement 替换此字符串所有的regex字符串;
boolean startsWith(String prefix) 测试此字符串是否以指定的前缀开始.
String[] split(String regex) 把字符串按指定的字符串分隔开。
String substring(int beginIndex) 返回一个新的字符串,从beginIndex开始截取,它是此字符串的一个子字符串;
String substring(int beginIndex, int endIndex) 返回一个新字符串,它是此字符串的一个子字符串;[begin,end)
char[] toCharArray() 将此字符串转换为一个新的字符数组。
String toLowerCase() 将此 String 中的所有字符都转换为小写;
String toUpperCase() 转成大写;
static String valueOf(基本类型 obj) 把基本类型值转成字符串;
String trim() 忽略字符串前导空白和尾部空白。

String小练习

  1. 判断字符串是否由纯数字组成:

package reviewDemo;

public class Demo20 {
    public static void main(String[] args) {
        String s1 = "123456789";
        String s2 = "12345  6789";
        System.out.print(isnum(s1));
        System.out.print(isnum(s2));
    }
    
    public static boolean isnum(String s){
        //将字符串参数转为字符数组
        char []ch = s.toCharArray();
        //循环字符数组,判断每一个元素是否在数字对应的字符区间内
        for (char c : ch) {
            //判断字符是否在[0-9]这个区间内部
            if(!(c > '0' && c <= '9')){
                return false;
            }
        }
        return true;
    }
}

输出:

true
false
  1. 判断字符串是否为空:
分析:
字符串的空有两种情况:1null2"";

package reviewDemo;

public class Demo21 {
    public static void main(String[] args) {
        
        String s1 = "";
        System.out.println(isimpty(s1));
        
    }
    
    public static String isimpty(String s){

        if(s != null && !"".equals(s)){
            return "不为空";
        }
        return "为空!";
    }
}

StringBuffer 与 StringBuilder

String是不可变类,一旦String对象被创建,包含在对象中的字符序列是不可变的,直到对象被销毁;
StringBuffer 与 StringBuilder对象则是可变的!

由于String创建的对象是一个不变化的对象,为了方便在我们使用过程中修改字符串的内容,java为我们提供了StringBUffer和StringBuilder两个类
StringBuffer是线程安全的类,StringBuilder是线程不安全的类。在多线程环境下使用StringBuffer。


在平时的编程中,我们为了方便,总是使用字符串之间相互加减进行操作修改字符串的内容。
比如:
    String a  = "h";
    String b = "e";
    String c = "c";
    String result = a + b +c +"result" ;
    
如上方式是不高效的,推荐修改为StringBuilder或StringBuffer。下列程序验证了程序的高效性。


package reviewDemo;

public class Demo22 {
    public static void main(String[] args) {
        
        String s = "";
        long begintime = System.currentTimeMillis();
        for(int i = 1;i <= 100000;i++){
            s += i;
        }
        
        
        long endtime = System.currentTimeMillis();
        long time = endtime - begintime;
        System.out.println("运行时间为:"+time);
        
        StringBuffer s1 = new StringBuffer();
        s = "";
        begintime = System.currentTimeMillis();
        for(int i = 1;i <= 100000;i++){
            s = ""+i;
            s1 = new StringBuffer(s);
        }
        
        endtime = System.currentTimeMillis();
        time = endtime - begintime;
        System.out.println("运行时间为:"+time);
        
    }
}

输出:
运行时间为:82922
运行时间为:15
可以看得出:StringBuffer这两个效率相当高!

StringBuffer 与 StringBuilder

  • StringBuffer: 是线程安全的;
  • StringBuilder: 是线程不安全的,性能高点,推荐使StringBuilder;(jdk1.5出现)
  • StringBuffer的字符序列是可变的(通过append等方法操作)
  • StringBuffer 和 String之间的转换;
  • String toString() 返回此序列中数据的字符串表示形式。
  • StringBuffer(String str):以指定的字符串创建StringBuffer对象。

StringBuffer方法

方法名 意义
public StringBuilder() 构造一个不带任何字符的StringBuilder对象。
StringBuffer(String str) 构造一个字符串缓冲区,并将其内容初始化为指定的字符串内容。
StringBuffer append(Object o) 将指定的任意类型对象追加到此StringBuffer 对象。
StringBuffer insert(int offset, Object o) 将任意类型参数的字符串表示形式插入此序列中。
StringBuffer delete(int start, int end) 移除此序列的子字符串中的字符。
StringBuffer deleteCharAt(int index) 移除此序列指定位置的 char。

练习

  1. 需求:用StringBuilder 或StringBuffer: 把字符串“ABCDE”; 转变成字符串“A,B,C,D”


public class Demo23 {
    public static void main(String[] args) {
        //第一种方法:往里面插入;
        StringBuilder sb = new StringBuilder("ABCDE");
        sb.deleteCharAt(sb.length()-1);
        System.out.println(sb);
        for (int i = 0; i < sb.length(); i+=2) {
            sb.insert(i, ",");
        }
        sb.deleteCharAt(0);
        
        System.out.println(sb);
        
        
        //第二种方法:往里面追加,要追加必须遍历,必须换为数组!
        sb = new StringBuilder("ABCDE");
        sb.deleteCharAt(sb.length()-1);
        System.out.println(sb);
        char []cs = sb.toString().toCharArray();
        StringBuilder sb1 = new StringBuilder();
        for (char c : cs) {
            sb1.append(c).append(",");
        }
        sb1.deleteCharAt(sb1.length()-1);
        System.out.println(sb1);
    } 
}
  1. 编写一个程序,这个程序把一个整数数组中的每个元素用逗号连接成一个字符串,例如,根据内容为{1,2,3}的数组形成内容为"1,2,3"的字符串。

package reviewDemo;
/**
 * 编写一个程序,
 * 这个程序把一个整数数组中的每个元素用逗号连接成一个字符串,
 * 例如,根据内容为{1,2,3}的数组形成内容为"1,2,3"的字符串。
 */

public class Demo24 {
    public static void main(String[] args) {
        int []i = {1,2,3,4,5};
        StringBuilder sb = new StringBuilder();
        for (int j : i) {
            sb.append(j).append(",");
        }
        sb.deleteCharAt(sb.length()-1);
        System.out.println(sb);
    }
}

注意:

字符串是任何程序语言的最常用、处理操作最多的。即使在大数据领域也是以处理文本数据为主。