美文网首页程序员
JAVA中的String类、StringBuffer类、Stri

JAVA中的String类、StringBuffer类、Stri

作者: Swen_9826 | 来源:发表于2018-11-23 10:57 被阅读33次
    小伙子!打起精神来,让自己活的贵一点!

    String类、StringBuffer类、StringBuilder类三者之间的关系

    • String类对字符串的保存格式:
    private final char value[];
    

    从源码中可以看出来,它是被final修饰的,是不可变的,从它被创建直至被销毁,它的字符序列都没有改变,我们对它的一系列操作都是通过创建新的String对象来完成的。

    String的相关知识

    • StringBuilder、StringBuffer两个类对字符串的保存格式:
    char[] value;
    

    StringBuilder、StringBuffer两个类都继承自抽象类AbstractStringBuilder,它们是可变的。

    • StringBuilder、StringBuffer与String类之间的转换
    public abstract String toString();
    

    当我们通过StringBuilder、StringBuffer对象进行一系列操作后得到了我们最终想要的字符串之后,可以通过toString()方法来将StringBuilder、StringBuffer对象转化为String对象。

    StringBuilder a  = new StringBuilder("hello");
    

    同时也可以将String类型转换为StringBuilder或者StringBuffer类型。

    线程安全相关的问题

    • String类

    String中的对象是不可变的,可以理解为常量,显然线程安全

    • StringBuffer类与StringBuilder类
    public synchronized StringBuffer append(Object obj) {
        super.append(String.valueOf(obj));
        return this;
    }
    public synchronized StringBuffer reverse() {
        super.reverse();
        return this;
    }
    

    从代码可以看出来StringBuffer类是被synchronized修饰的,所以是线程安全的,StringBuffer和StringBuilder类功能基本相似,最大的区别在与StringBuilder是没有被synchronized修饰的,因此线程不安全,但是StringBuilder类的速度要比String类与StringBuffer要快一点。

    StringBuffer是线程安全的,这意味着它们已经同步方法来控制访问,以便只有一个线程可以在同一时间访问一个StringBuffer对象同步代码。因此,StringBuffer的对象通常在多线程环境中是安全的,使用多个线程可以试图同时访问相同StringBuffer对象。

    StringBuilder类不是线程安全的。由于不同步,StringBuilder的性能可以比StringBuffer更好。因此,如果在单线程环境中工作,使用StringBuilder,而不是StringBuffer可能会有更高的性能。

    • 总结

    String 字符串常量
    StringBuffer 字符串变量(线程安全)
    StringBuilder 字符串变量(非线程安全)
    在大部分情况下速度: StringBuilder > StringBuffer
    在大部分情况下速度: StringBuffer > String

    速度测试代码

    public class Test {
        
        final static int time = 50000; //循环次数 
        
        public static void main(String[] args) {
            Test test = new Test();
            
            String s1 =  "String类测试:";
            StringBuffer st1 = new StringBuffer( "StringBuffer类测试:");
            StringBuilder st2 = new StringBuilder( "StringBuilder类测试:");
                        
            test.test(s1);      
            test.test(st1);     
            test.test(st2);
            test.test2();
            test.test3();
        }       
        /*
         * String类测试方法
         */
        public void test(String s){
            long begin = System.currentTimeMillis();//获取当前系统时间(毫秒数),开始
            for(int i=0; i<time; i++){
                s += "hello";
            }
            long over = System.currentTimeMillis();//获取当前系统时间(毫秒数),结束
            System.out.println("操作"+s.getClass().getName()+"类型使用的时间为:"+(over-begin)+"毫秒");
        }
        /*
         * StringBuffer类测试方法
         */
        public void test(StringBuffer s){
            long begin = System.currentTimeMillis();
            for(int i=0; i<time; i++){
                s.append("hello");
            }
            long over = System.currentTimeMillis();
            System.out.println("操作"+s.getClass().getCanonicalName()+"类型使用的时间为:"+(over-begin)+"毫秒");
        }
        /*
         * StringBuilder类测试方法
         */
        public void test(StringBuilder s){
            long begin = System.currentTimeMillis();
            for(int i=0; i<time; i++){
                s.append("hello");
            }
            long over = System.currentTimeMillis();
            System.out.println("操作"+s.getClass().getName()+"类型使用的时间为:"+(over-begin)+"毫秒");
        }
        
        /*对 String 直接进行字符串拼接的测试*/
        public void test2(){//操作字符串对象引用相加类型使用的时间
            String s2 = "abcd";
            long begin = System.currentTimeMillis();
            for(int i=0; i<time; i++){
                String s = s2 + s2 +s2;
            }
            long over = System.currentTimeMillis();
            System.out.println("操作字符串对象引用相加类型使用的时间为:"+(over-begin)+"毫秒");
        }
        public void test3(){//操作字符串相加使用的时间
            long begin = System.currentTimeMillis();
            for(int i=0; i<time; i++){
                String s = "abcd" + "abcd" +  "abcd";
            }
            long over = System.currentTimeMillis();
            System.out.println("操作字符串相加使用的时间为:"+(over-begin)+"毫秒");
        } 
    }
    
    //测试结果:
    操作java.lang.String类型使用的时间为:9954毫秒
    操作java.lang.StringBuffer类型使用的时间为:10毫秒
    操作java.lang.StringBuilder类型使用的时间为:0毫秒
    操作字符串对象引用相加类型使用的时间为:15毫秒
    操作字符串相加使用的时间为:0毫秒
    

    结果可以看出,在不必考虑到线程同步问题,我们应该优先使用StringBuilder类;如果要保证线程安全,自然是StringBuffer;能直接操作字符串不用字符串引用就直接操作字符串

    StringBuilder类与StringBuffer类的相同点

    方法 说明
    StringBuffer append(参数) 追加内容到当前StringBuffer对象的末尾,类似于字符串的连接
    StringBuffer deleteCharAt(int index) 删除指定位置的字符,然后将剩余的内容形成新的字符串
    StringBuffer insert(位置, 参数) 在StringBuffer对象中插入内容,然后形成新的字符串
    StringBuffer reverse() 将StringBuffer对象中的内容反转,然后形成新的字符串
    void setCharAt(int index, char ch) 修改对象中索引值为index位置的字符为新的字符ch
    void trimToSize() 将StringBuffer对象的中存储空间缩小到和字符串长度一样的长度,减少空间的浪费,和String的trim()是一样的作用
    StringBuffer delete(int start, int end) 删除指定区域的字符串
    StringBuffer replace(int start, int end, String s) 用新的字符串替换指定区域的字符串
    void setlength(int n) 设置字符串缓冲区大小
    int capacity() 获取字符串的容量
    void ensureCapacity(int n) 确保容量至少等于指定的最小值。如果当前容量小于该参数,然后分配一个新的内部数组容量更大。新的容量是较大的
    getChars(int start,int end,char chars[],int charStart); 将字符串的子字符串复制给数组

    StringBuilder类与StringBuffer类常用方法测试代码

    public class Test { 
        
        public static void main(String[] args) {
            Test test = new Test();
            StringBuffer strbf = new StringBuffer("Hello Swen");    
            StringBuilder strbl = new StringBuilder(30);
            
            System.out.println("testStringBuffer如下:");
            test.testStringBuffer(strbf);
            System.out.println("testStringBuilder如下:");
            test.testStringBuilder(strbl);
        }       
        /*
         * StringBuffer类测试方法
         */
        public void testStringBuffer(StringBuffer str){
            //增加字符串内容的方法
            //append(参数),追加内容到当前对象的末尾
            str.append(" 你要加油学习!");
            System.out.println("追加内容到当前对象的末尾:"+str);        
            // insert(位置, 参数),在对象中插入内容
            str.insert(10,',');
            System.out.println("在对象中插入内容:"+str);
          
            //操作字符串内容的方法
            //delete(int start, int end),删除指定区域的字符串
            str.delete(10, 18);
            System.out.println("删除指定区域的字符串:"+str);
            //deleteCharAt(int index),删除指定位置的字符
            str.deleteCharAt(10);
            System.out.println("删除指定位置的字符:"+str);
            //setCharAt(int index, char newChar),修改对象中索引值为index位置的字符为新的字符ch
            str.setCharAt(5, '-');
            System.out.println("修改对象中索引值为index位置的字符为新的字符ch:"+str);
            //replace(int start, int end, String s), 用新的字符串替换指定区域的字符串
            str.replace(6, 10, "world");
            System.out.println("用新的字符串替换指定区域的字符串:"+str);
            // reverse()内容反转
            str.reverse();
            System.out.println("内容反转:"+str);
            //将字符串的子字符串复制给数组。
            char[] ch  = new char[5];
            str.getChars(0, 3, ch, 0);
            System.out.println("将字符串的子字符串复制给数组:"+Arrays.toString(ch));
        }
        /*
         * StringBuilder类测试方法
         */
        public void testStringBuilder(StringBuilder str){
            
            str.append("Hello Swen");
            System.out.println("追加内容到当前对象的末尾:"+str);
            //length(),获取字符串长度
            System.out.println("字符串长度为:"+str.length());
            //capacity(),获取字符串的容量
            System.out.println("字符串容量为:"+str.capacity());
            
            //有关字符串空间的方法
            //setLength(int newSize),设置字符串缓冲区大小
            str.setLength(20);
            System.out.println("setLength后,字符串长度为:"+str.length());
            System.out.println("setLength后,字符串容量为:"+str.capacity());
    
            //trimToSize(),存储空间缩小到和字符串长度一样的长度
            str.trimToSize();
            System.out.println("trimToSize后,字符串长度为:"+str.length());
            System.out.println("trimToSize后,字符串容量为:"+str.capacity());
        }
        
    }
    

    StringBuilder类与StringBuffer类常用方法测试结果

    testStringBuffer如下:
    追加内容到当前对象的末尾:Hello Swen 你要加油学习!
    在对象中插入内容:Hello Swen, 你要加油学习!
    删除指定区域的字符串:Hello Swen!
    删除指定位置的字符:Hello Swen
    修改对象中索引值为index位置的字符为新的字符ch:Hello-Swen
    用新的字符串替换指定区域的字符串:Hello-world
    内容反转:dlrow-olleH
    将字符串的子字符串复制给数组:[d, l, r,  ,  ]
    
    testStringBuilder如下:
    追加内容到当前对象的末尾:Hello Swen
    字符串长度为:10
    字符串容量为:30
    setLength后,字符串长度为:20
    setLength后,字符串容量为:30
    trimToSize后,字符串长度为:20
    trimToSize后,字符串容量为:20
    

    相关文章

      网友评论

        本文标题:JAVA中的String类、StringBuffer类、Stri

        本文链接:https://www.haomeiwen.com/subject/vmmrqqtx.html