Java 中 String 以及 StringBuffer 和 StringBuider

String

在 Java 中定义一个变量为 string 类型如下:

// 定义变量 url 类型为字符串

       String url = "www.baidu.com";

String字符串与数组有一个共同点,就是它们被初始化后,长度是不变的,并且内容也不变。如果要改变它的值,就会产生一个新的字符串:

String str = "Hello ";
str += "World!";

程序首先产生了str1字符串,并在内存中申请了一段空间。此时要追加新的字符串是不可能的,因为字符串被初始化后,长度是固定的。如果要改变它,只有放弃原来的空间,重新申请能够容纳“Hello World!”字符串的内存空间,然后将“Hello World!”字符串放到内存中。

实际上,String 是java.lang包下的一个类,按照标准的面向对象的语法,其格式应该为:

String stringName = new String("string content");

例如:

String url = new String("http://www.awen.me");

但是由于String特别常用,所以Java提供了一种简化的语法。

使用简化语法的另外一个原因是,按照标准的面向对象的语法,在内存使用上存在比较大的浪费。例如String str = new String(“abc”);实际上创建了两个String对象,一个是”abc”对象,存储在常量空间中,一个是使用new关键字为对象str申请的空间。

常用操作

下面是关于字符串的替换、切割、长度使用方法

String url = "www.baidu.com";

System.out.println(url.length());  //输出 13,无论是数字还是字母或汉字,每个字符的长度都是1

String str = "123456789";

System.out.println(str.charAt(0)); // 输出1,str 的索引 0 是1

String str1 = "www.awen.me";

String str2 = str1.replace("awen.me","google.com");

System.out.println(str2); //输出 www.google.com

String str3 = "www_awen_me";

String strArr[] = str3.split("_");

System.out.println(Arrays.toString(strArr));//输出 [www, awen, me]

StringBuffer

String 的值是不可变的,每次对String的操作都会生成新的String对象,不仅效率低,而且耗费大量内存空间。

StringBuffer类和String类一样,也用来表示字符串,但是StringBuffer的内部实现方式和String不同,在进行字符串处理时,不生成新的对象,在内存使用上要优于String。

StringBuffer 默认分配16字节长度的缓冲区,当字符串超过该大小时,会自动增加缓冲区长度,而不是生成新的对象。

/**
        * String 的值是不可变的,每次对 String 的操作都会生成新的 String 对象,不仅效率低,而且还耗费大量的内存空间
        *
        * StringBuffer 和 String 类一样,也是用来表示字符串,但 StringBuffer 不生成新的对象,在内存使用上要优于 String
        */

       StringBuffer str1 = new StringBuffer(); //分配16个字节长度的缓冲区
       StringBuffer str2 = new StringBuffer(512); // 分配512个字节长度的缓冲区


       // 在缓存区中存放了字符串,并且在后面预留了16个字节长度的缓冲区
       StringBuffer str3 = new StringBuffer("www.awen.me");


       /**
        * StringBuffer类的主要方法
        */


       StringBuffer str4 = new StringBuffer("abcd");

append() 方法

// append 方法

StringBuffer str5 = str4.append(true);


System.out.println(str4 == str5);//输出 true,注意这里是 str4 的内容变了,不是其地址变了。


String str6 = "adcd";
String str7 = str6 + "efg";

System.out.println(str6 == str7); // 输出 false,因为地址变了

/**字符串的”+“操作实际上也是先创建一个StringBuffer对象,然后调用append()方法将字符串片段拼接起来,最后调用toString()方法转换为字符串。
 *
 *  这样看来,String的连接操作就比StringBuffer多出了一些附加操作,效率上必然会打折扣。
 */

deleteCharAt() 和 delete()

deleteCharAt() 方法用来删除指定位置的字符,并将剩余的字符形成新的字符串。

StringBuffer str = new StringBuffer("sswsdeed");
str.deleteCharAt(3); // 删除索引为3的字符,即第三个 s,输出 sswdeed
System.out.println(str);
str.delete(1,4); //删除1-4之间的字符,即输出 seed
System.out.println(str);

insert()

insert() 用来在指定位置插入字符串,可以认为是append()的升级版。

StringBuffer str = new StringBuffer("sswsdeed");
str.deleteCharAt(3); // 删除索引为3的字符,即第三个 s,输出 sswdeed
System.out.println(str);
str.delete(1,4); //删除1-4之间的字符,即输出 seed
System.out.println(str);

str.insert(3,"xyz"); //输出 seexyzd

System.out.println(str);

setCharAt()

setCharAt() 方法用来修改指定位置的字符。

StringBuffer str = new StringBuffer("sswsdeed");
str.deleteCharAt(3); // 删除索引为3的字符,即第三个 s,输出 sswdeed
System.out.println(str);
str.delete(1,4); //删除1-4之间的字符,即输出 seed
System.out.println(str);

str.insert(3,"xyz"); //输出 seexyzd

System.out.println(str);

str.setCharAt(3,'z'); //输出 seezyzd

System.out.println(str);

String 和 StringBuffer 的效率对比

public static void main(String[] args) {


       String fragment = "abcdefghijklmnopqrstuvwxyz";

       int times = 10000;


       // 测试 string 对象


       long timeStart1 = System.currentTimeMillis();

       String str1 = "";

       for (int i = 0; i < times; i++) {

           str1 +=fragment;

       }

       long timeEnd1 = System.currentTimeMillis();

       System.out.println("String = ["+(timeEnd1 - timeStart1)+ "ms]");



       // 通过StringBuffer
       long timeStart2 = System.currentTimeMillis();

       StringBuffer str2 = new StringBuffer();

       for (int i = 0; i < times; i++) {

           str2.append(fragment);

       }

       long timeEnd2 = System.currentTimeMillis();

       System.out.println("StringBuffer= [" + (timeEnd2 - timeStart2) + "ms]");


   }

结果:

StringBuilder类

StringBuilder类和StringBuffer类功能基本相似,方法也差不多,主要区别在于StringBuffer类的方法是多线程安全的,而StringBuilder不是线程安全的,相比而言,StringBuilder类会略微快一点。

使用环境:

  • 操作少量的数据使用 String;
  • 单线程操作大量数据使用 StringBuilder;
  • 多线程操作大量数据使用 StringBuffer。