String、StringBuilder、StringBuffer 学习与深入
1 学习的知识是什么String:字符串,一旦创建里面的内容就不可变每次使用拼接都创建一个新的对象而原有的对象依旧存在。StringBuilder:可变字符串线程不安全每次拼接字符串只会在字符串后面追加字符而不是创建新的对象字符串可修改。StringBuffer:可变字符串线程安全每次拼接字符串只会在字符串后面追加字符而不是创建新的对象字符串可修改。2. 三者的字符串特性1.String每次拼接都会创建新的对象,StringBuffer,StringBuilder不会2.StringBuffer,StringBuilder可以对字符串进行各种操作package com.se.string; /*** * date:2026/5.11 */ public class StringTest { public static void main(String[] args) { String str hello; System.out.println(打印:System.identityHashCode(str));//打印:460141958 str world; System.out.println(打印:System.identityHashCode(str));//打印:1163157884 //String的地址不同说明不是同一个对象 StringBuilder sbd new StringBuilder(hello); System.out.println(打印:System.identityHashCode(sbd));//打印:1956725890 sbd.append(world); System.out.println(打印:System.identityHashCode(sbd));//打印:1956725890 //StringBuilder的地址一样说明是同一个对象 StringBuffer sbf new StringBuffer(hello); System.out.println(打印:System.identityHashCode(sbf));//打印:356573597 sbf.append(world); System.out.println(打印:System.identityHashCode(sbf));//打印:356573597 //StringBuffer的地址一样说明是同一个对象 //这些方法StringBuffer,StringBuilder都一样唯一的区别是StringBuffer的方法都加了synchronized所以线程安全不过效率慢一点 //1.append();在字符串后面追加字符 sbf.append(1); System.out.println(sbf);//打印:helloworld1 //2.insert();在字符串中间插入字符 sbf.insert(6,StringBuffer); System.out.println(sbf);//打印:helloStringBufferworld1 从0开始算位置 //3.delete(start,end);删除字符串中间的字符 sbf.delete(5,12); System.out.println(sbf);//打印:helloworld1 //4.replace(start,end,chars);字符串替换 sbf.replace(5,11,StringBuffer); System.out.println(sbf);//打印:helloStringBufferworld1 //5.reverse();反转字符串 sbf.reverse(); System.out.println(sbf);//打印:1dlrowgnitpircSihell //6.toString();将StringBuffer转换为String String str1 sbf.toString(); System.out.println(str1);//打印:1dlrowgnitpircSihell } }3. StringBuffer和StringBuilder的安全性分析3.1性能分析1.在单线程环境下StringBuilder的性能优于StringBuffer2.在多线程环境下StringBuffer的安全性可以得到保证3.以上原因是StringBuffer的所有方法是被synchronized修饰的package com.se.string; public class StringTest2 { public static int COUNT 1000000; public static void main(String[] args) { // 预热 JVM warmUp(); // StringBuilder long start1 System.currentTimeMillis(); StringBuilder sb new StringBuilder(); for (int i 0; i COUNT; i) { sb.append(a); } long time1 System.currentTimeMillis() - start1; // StringBuffer long start2 System.currentTimeMillis(); StringBuffer sbf new StringBuffer(); for (int i 0; i COUNT; i) { sbf.append(a); } long time2 System.currentTimeMillis() - start2; System.out.println(StringBuilder 耗时 time1 ms);//StringBuilder 耗时17ms System.out.println(StringBuffer 耗时 time2 ms);//StringBuffer 耗时27ms System.out.println(StringBuffer 比 StringBuilder 慢约 (time2 - time1) ms);//StringBuffer 比 StringBuilder 慢约 10ms } // JVM 预热让后续测试更稳定 private static void warmUp() { for (int k 0; k 10; k) { StringBuilder sb new StringBuilder(); for (int i 0; i 10000; i) { sb.append(i); } } } }实际来看在单线程场景下两种的效率差别不大用stringbuilder更多只是为了满足规范---这是在单线程场景下使用3.2 线程安全1. 开启10个线程每个线程都添加1000个a然后查看是否添加够了10000个apackage com.se.string; public class StringTest3 { private static final int THREAD_COUNT 10; private static final int APPEND_COUNT 1000; public static void main(String[] args) throws InterruptedException { // 测试 StringBuilder线程不安全 StringBuilder sb new StringBuilder(); Thread[] threads1 new Thread[THREAD_COUNT]; for (int i 0; i THREAD_COUNT; i) { threads1[i] new Thread(() - { for (int j 0; j APPEND_COUNT; j) { sb.append(a); } }); threads1[i].start(); } for (Thread t : threads1) { t.join(); // 等所有线程执行完 } System.out.println(StringBuilder 预期长度 (THREAD_COUNT * APPEND_COUNT));//StringBuilder 预期长度10000 System.out.println(StringBuilder 实际长度 sb.length());//StringBuilder 实际长度5423 System.out.println(---------------); // 测试 StringBuffer线程安全 StringBuffer sbf new StringBuffer(); Thread[] threads2 new Thread[THREAD_COUNT]; for (int i 0; i THREAD_COUNT; i) { threads2[i] new Thread(() - { for (int j 0; j APPEND_COUNT; j) { sbf.append(a); } }); threads2[i].start(); } for (Thread t : threads2) { t.join(); } System.out.println(StringBuffer 预期长度 (THREAD_COUNT * APPEND_COUNT));//StringBuffer 预期长度10000 System.out.println(StringBuffer 实际长度 sbf.length());//StringBuffer 实际长度10000 } }因为stringbuffer带锁所以线程是安全的而stringBuilder没有锁所以数据会丢失
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2605769.html
如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!