java字符串处理--String,StringBuffer,StringBuilder类

来源:互联网 发布:综合布线仿真软件下载 编辑:程序博客网 时间:2024/04/29 05:00

在java程序中,字符串的处理,是非常常见的。java中,字符串处理的类有,String,StringBuffer,StringBuilder类。下面简单总结下java程序里的字符串各种处理的区别。

String literal(字面量字符串)

字面量字符串(String literal)就是那些直接在代码文件里用双引号扩起来的字符串申明,比如String str=”abc”。当字面量字符串被创建的时候,JVM就会把”abc”这个字符串对象放到字符串常量池里。如果下次再”abc”这个字符串的引用,则直接使用常量池里的对象,而不是重新创建新的String对象。

public class TestStringLiteral {    public static void main( String[] args ){        String str1 = "hello";        String str2 = "hello";        System.out.println(str1 == str2);        //true        //字面量字符串不会被重复创建    }}

String类

String类是不可变(immutable)的。在java中,所有不可变对象都是线程安全的。所以,字符串是不能被两个线程同时使用的。字符串对象一旦被分配,就永远不会再被改变。所有针对String类做改变的操作,都是创建了一个新的字符串。而之前对象的内容,是不会被改变。

public class TestString {    public static void main( String[] args ){        String str1 = new String("hello");        String str2 = str1;        System.out.println(str1 == str2);        //true        str2 = str2.replace('h', 'H');        //新建了一个新的String对象        System.out.println(str1);        //hello        System.out.println(str2);        //Hello        System.out.println(str1 == str2);        //false    }}

intern函数

使用new创建的String对象,是不会放到字符串常量池中的。如果想把new出来的String对象放到字符串常量池中,可以使用String提供的intern函数。intern函数会从字符串常量池中查询当前字符串是否存在,若不存在就会将当前字符串放入常量池中。

public class TestIntern {    public static void main( String[] args ){        String str1 = new String("hello");        String str2 = "hello";        String str3 = str1.intern();        System.out.println(str1 == str2);        //false        System.out.println(str2 == str3);        //true        //都指向常量池里的对象    }}

字符串常量池的好处,就是减少相同字符串的创建,节约内存。但字符串常量池里的所有字符串都是不会被GC回收的。

字符串常量池的基础就是上面介绍的String类是不可变的。

String几个小问题

1.如下代码,创建了几个String对象

String s = new String("abc")

A:创建了两个对象。第一个对象是”abc”字符串存储在常量池中,第二个对象在JAVA Heap中的 String 对象。正如上面TestIntern的例子代码里,str1和str2并没有指向同一个对象。

2.下面代码,创建了几个对象

String test = "a" + "b" + "c";

A:只创建了一个对象,在常量池中也只保存一个引用,即字符串abc。因为,JVM对初始化的连接操作字符串进行了优化。

StringBuilder

StringBuffer是可变的。StringBuffer被创建了之后,会在堆(heap)内存区new一块内存。StringBuffer的所有修改操作,都是直接改变heap区域内的值。同时,StringBuilder也是线程不安全的,如果有两个线程同时对StringBuilder对象进行修改,则会出问题。

public class TestStringBuilder {    public static void main( String[] args ){        StringBuilder strBuilder1 = new StringBuilder("hello");        StringBuilder strBuilder2 = strBuilder1;        System.out.println(strBuilder1 == strBuilder2);        //true        strBuilder1.append(" bye");        System.out.println(strBuilder1);        //hello bye        //因为StringBuilder对象直接改变内存里值        System.out.println(strBuilder2);        //hello bye        System.out.println(strBuilder1 == strBuilder2);        //true    }}

StringBuffer

StringBuffer类和StringBuilder类一样,都是可变的,同时也拥有相同的函数接口。但与StringBuilder不同的是,StringBuffer是线程安全的。由于,每个操作都需要进行线程同步操作。所以,StringBuffer类会比StringBuilder类慢。除非有特殊需要,否则,最好是使用StringBuilder来代替StringBuffer。

字符串连接性能比较

public class StringTest {    final static String TEST_STRING = "abcdefghijklmnopsdsdfsad";    final static int LOOP_COUNT = 10000;    static String useString(){        String result = "";        for (int i=0; i<LOOP_COUNT; ++i){            result += TEST_STRING;        }        return result;    }    static String useStringBuilder(){        StringBuilder builder = new StringBuilder();        for (int i=0; i<LOOP_COUNT; ++i){            builder.append(TEST_STRING);        }        return builder.toString();    }    static String userStringBuffer(){        StringBuffer buffer = new StringBuffer();        for (int i=0; i<LOOP_COUNT; ++i){            buffer.append(TEST_STRING);        }        return buffer.toString();    }    public static void main( String[] args ) {        long begin = System.currentTimeMillis();        useString();        long strEnd = System.currentTimeMillis();        useStringBuilder();        long builderEnd = System.currentTimeMillis();        userStringBuffer();        long bufferEnd = System.currentTimeMillis();        System.out.println("String time:"+ (strEnd - begin));        System.out.println("StringBuilder time:" + (builderEnd - strEnd));        System.out.println("StringBuffer time:" + (bufferEnd - builderEnd));    }}

上面程序,在我的机器上的输出结果为:

String time:2802StringBuilder time:3StringBuffer time:11

从上面的结果可以看到,String类比StringBuilder类的性能要差很多。所以,千万不能使用”+”进行String字符串的拼接操作,要优先使用StringBuilder的append操作。

0 0
原创粉丝点击