JDK源码阅读-------自学笔记(十二)(java.lang.StringBuffer和StringBuilder比较)

StringBuilder结构

  • 明显的看到StringBuilder跟String相似的存在char数组
  • 区别是StringBuilder的char[]数组不是final修饰的,所以是可以多次改变的,随时可以改变源码
1 abstract class AbstractStringBuilder implements Appendable, CharSequence {
2     /**
3      * The value is used for character storage.
4      */
5     char[] value;
6     
7     ....
View Code

核心要点

  • final的有无区别
  • 可以成为可变的字符序列

StringBuffer结构

 

  • 明显的看到StringBuffer跟String相似的存在char数组
  • 区别是StringBuffer的char[]数组不是final修饰的,所以是可以多次改变的,随时可以改变源码
    1 abstract class AbstractStringBuilder implements Appendable, CharSequence {
    2     /**
    3      * The value is used for character storage.
    4      */
    5     char[] value;
    6     
    7     ....
    8 }
    View Code

核心要点

  • final的有无区别
  • 可以成为可变的字符序列

StringBuffer和StringBuilder区别

不同:

  • StringBuffer线程安全,效率低
  • StringBuilder线程不安全,效率高
  • 一般使用StringBuilder,因为一般不涉及线程安全

相同:

  • 都是AbstractStringBuilder子类

实例:

可变字符序列,内容可以随意修改

 1       StringBuilder stringBuilder = new StringBuilder("abcdfg");
 2 
 3        System.out.println(Integer.toHexString(stringBuilder.hashCode()));
 4 
 5         System.out.println(stringBuilder);
 6 
 7 
 8         stringBuilder.setCharAt(3, 'L');
 9         System.out.println(Integer.toHexString(stringBuilder.hashCode()));
10 
11         System.out.println(stringBuilder);
View Code

 

基本用法

    • 添加26个字母
       1        // 初始化StringBuffer
       2         StringBuffer twentySixLetter = new StringBuffer();
       3 
       4         for (int i = 0; i < 26; i++) {
       5 
       6             // 字符增加
       7             char needTransformationLetter = (char) ('a' + i);
       8 
       9             // 添加字母到stringBuffer
      10             twentySixLetter.append(needTransformationLetter);
      11 
      12         }
      13 
      14         System.out.println("打印26个字母:" + twentySixLetter);
      View Code
    • 倒叙字符序列
      1         twentySixLetter.reverse();
      2 
      3         System.out.println("打印26个字母的倒叙:" + twentySixLetter);
      View Code
    • 修改制定位置的字符
      1         twentySixLetter.setCharAt(6,'走');
      2         System.out.println("修改第六个位置的字符:" + twentySixLetter);
      View Code
    • 指定位置插入字符
      1         twentySixLetter.insert(0,'再');
      2         System.out.println("在第一个位置插入字符:" + twentySixLetter);
      View Code

注:

观察源码

 

// 继承父类方法

super.insert(offset, c);

// 返回本身对象

return this;

这就意味着可以多次的使用这个对象,一般称之为 链式调用

核心就是:

调用了 return this;

如下:

1        // 指定位置插入字符
2         twentySixLetter.insert(0,'再').insert(1,'三');
3         System.out.println("在第一个位置插入字符:" + twentySixLetter);
View Code
  • 删除某个区间的字符,或删除某个位置的字符 delete也是链式调用,也可以连续删除
    1        // 删除区间字符
    2         twentySixLetter.delete(20,26);
    3         System.out.println("删除后的字符:" + twentySixLetter);
    View Code
  • 删除某个字符
    1         //删除某个字符
    2         twentySixLetter.deleteCharAt(0).deleteCharAt(0);
    3         System.out.println("删除第一个第二个字符:" + twentySixLetter);
    View Code
  • 获取某个字符
    1         //获取字符
    2         twentySixLetter.charAt(15);
    3         System.out.println("获取字符:" + twentySixLetter);
    View Code 

 

不可变和可变字符序列使用陷阱

  • 循环累加字符串的时候,不建议如下写法,会创建大量对象,占用过多资源,消耗服务器资源
    1         String wrongWriteString = "";
    2 
    3         for (int i = 0; i < 5000; i++) {
    4 
    5             //相当于产生了10000个对象
    6             wrongWriteString = wrongWriteString + i;
    7         }
    8 
    9         System.out.println(wrongWriteString);
    View Code
  • 建议如下写法,可以减少创建对象和所消耗的时间
    1        StringBuilder stringBuilderRight = new StringBuilder("");
    2 
    3         for (int i = 0; i < 5000; i++) {
    4             stringBuilderRight.append(i);
    5         }
    6 
    7         System.out.println(stringBuilderRight);
    View Code
  • 效率,占用内存测试
     1         // 使用String进行字符串的拼接
     2         String stringWrong = "";
     3         //本质上使用StringBuilder拼接, 但是每次循环都会生成一个StringBuilder对象
     4         //获取系统剩余内存空间
     5         long num1 = Runtime.getRuntime().freeMemory();
     6         //获取系统的当前时间
     7         long time1 = System.currentTimeMillis();
     8         for (int i = 0; i < 5000; i++) {
     9             //相当于产生了10000个对象
    10             stringWrong = stringWrong + i;
    11         }
    12         long num2 = Runtime.getRuntime().freeMemory();
    13         long time2 = System.currentTimeMillis();
    14         System.out.println("String占用内存 : " + (num1 - num2));
    15         System.out.println("String占用时间 : " + (time2 - time1));
    16 
    17 
    18         /**使用StringBuilder进行字符串的拼接*/
    19         StringBuilder stringBuilderRight = new StringBuilder("");
    20         long num3 = Runtime.getRuntime().freeMemory();
    21         long time3 = System.currentTimeMillis();
    22         for (int i = 0; i < 5000; i++) {
    23             stringBuilderRight.append(i);
    24         }
    25         long num4 = Runtime.getRuntime().freeMemory();
    26         long time4 = System.currentTimeMillis();
    27         System.out.println("StringBuilder占用内存 : " + (num3 - num4));
    28         System.out.println("StringBuilder占用时间 : " + (time4 - time3));
    View Code

     

posted @ 2020-05-05 04:04  北极的大企鹅  阅读(263)  评论(0编辑  收藏  举报
阅读 - 79万