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 ....

核心要点

  • 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 }

核心要点

  • 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);

基本用法

    • 添加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);
    • 倒叙字符序列
      1         twentySixLetter.reverse();
      2
      3 System.out.println("打印26个字母的倒叙:" + twentySixLetter);
    • 修改制定位置的字符
      1         twentySixLetter.setCharAt(6,'走');
      2 System.out.println("修改第六个位置的字符:" + twentySixLetter);
    • 指定位置插入字符
      1         twentySixLetter.insert(0,'再');
      2 System.out.println("在第一个位置插入字符:" + twentySixLetter);

注:

观察源码

// 继承父类方法

super.insert(offset, c);

// 返回本身对象

return this;

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

核心就是:

调用了 return this;

如下:

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

    1        // 删除区间字符
    2 twentySixLetter.delete(20,26);
    3 System.out.println("删除后的字符:" + twentySixLetter);
  • 删除某个字符
    1         //删除某个字符
    2 twentySixLetter.deleteCharAt(0).deleteCharAt(0);
    3 System.out.println("删除第一个第二个字符:" + twentySixLetter);
  • 获取某个字符
    1         //获取字符
    2 twentySixLetter.charAt(15);
    3 System.out.println("获取字符:" + twentySixLetter);

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

  • 循环累加字符串的时候,不建议如下写法,会创建大量对象,占用过多资源,消耗服务器资源

    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);
  • 建议如下写法,可以减少创建对象和所消耗的时间
    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);
  • 效率,占用内存测试
     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));

JDK源码阅读-------自学笔记(十二)(java.lang.StringBuffer和StringBuilder比较)的更多相关文章

  1. JDK源码阅读-------自学笔记(一)(java.lang.Object重写toString源码)

    一.前景提要 Object类中定义有public String toString()方法,其返回值是 String 类型. 二.默认返回组成 类名+@+16进制的hashcode,当使用打印方法打印的 ...

  2. JDK源码阅读-------自学笔记(二十五)(java.util.Vector 自定义讲解)

    Vector 向量 Vector简述 1).Vector底层是用数组实现的List 2).虽然线程安全,但是效率低,所以并不是安全就是好的 3).底层大量方法添加synchronized同步标记,sy ...

  3. JDK源码阅读-------自学笔记(五)(浅析数组)

    一.数组基础 1.定义和特点 数组也可以看做是对象,数组变量属于引用类型,数组中每个元素相当于该队形的成员变量,数组对象存储在堆中. 2.初始化数组 常用类初始化 // 整型初始化 int[] int ...

  4. JDK源码阅读-------自学笔记(二十四)(java.util.LinkedList 再探 自定义讲解)

    一.实现get方法 1.一般思维实现思路 1).将对象的值放入一个中间变量中. 2).遍历索引值,将中间量的下一个元素赋值给中间量. 3).返回中间量中的元素值. 4).示意图 get(2),传入角标 ...

  5. 利用IDEA搭建JDK源码阅读环境

    利用IDEA搭建JDK源码阅读环境 首先新建一个java基础项目 基础目录 source 源码 test 测试源码和入口 准备JDK源码 下图框起来的路径就是jdk的储存位置 打开jdk目录,找到sr ...

  6. JDK源码阅读-ByteBuffer

    本文转载自JDK源码阅读-ByteBuffer 导语 Buffer是Java NIO中对于缓冲区的封装.在Java BIO中,所有的读写API,都是直接使用byte数组作为缓冲区的,简单直接.但是在J ...

  7. JDK源码阅读(三):ArraryList源码解析

    今天来看一下ArrayList的源码 目录 介绍 继承结构 属性 构造方法 add方法 remove方法 修改方法 获取元素 size()方法 isEmpty方法 clear方法 循环数组 1.介绍 ...

  8. JDK源码阅读(一):Object源码分析

    最近经过某大佬的建议准备阅读一下JDK的源码来提升一下自己 所以开始写JDK源码分析的文章 阅读JDK版本为1.8 目录 Object结构图 构造器 equals 方法 getClass 方法 has ...

  9. 手机自动化测试:appium源码分析之bootstrap十二

    手机自动化测试:appium源码分析之bootstrap十二   poptest是国内唯一一家培养测试开发工程师的培训机构,以学员能胜任自动化测试,性能测试,测试工具开发等工作为目标.如果对课程感兴趣 ...

  10. JDK源码阅读(1)_简介+ java.io

    1.简介 针对这一个版块,主要做一个java8的源码阅读笔记.会对一些在javaWeb中应用比较广泛的java包进行精读,附上注释.对于容易混淆的知识点给出相应的对比分析. 精读的源码顺序主要如下: ...

随机推荐

  1. AT-abc347(C,D)

    AtCoder Beginner Contest 347 C - Ideal Holidays 这场做得最头疼的题 分析 容易想到先用$(d_i+a+b-1)%(a+b)+1$把$d_i$映射到$[1 ...

  2. OpenHarmony中的HDF单链表及其迭代器

    概念 为了性能考虑,嵌入式系统一般使用C语言进行开发,由于C语言标准库没有封装链表,所以嵌入式系统一般自己设计和实现链表这种数据结构.单链表是链表中的一种,本文描述OpenAtom OpenHarmo ...

  3. .NET Emit 入门教程:第六部分:IL 指令:6:详解 ILGenerator 指令方法:方法调用指令

    前言: 经过前面几篇的学习,我们了解到指令的大概分类,如: 参数加载指令,该加载指令以 Ld 开头,将参数加载到栈中,以便于后续执行操作命令. 参数存储指令,其指令以 St 开头,将栈中的数据,存储到 ...

  4. Matplotlib Installing an official release from resources 源码安装Matplotlib官方版本

    Installation Installing an official release Matplotlib releases are available as wheel packages for ...

  5. linux ssh连接

    前言 整理以前的随笔. 正文 首先更新源 sudo apt-get update 安装ssh服务 sudo apt-get install openssh-server 检测是否已启动 ps -e | ...

  6. JavaScript如何判断一个元素是否在可视区域中?

    一.用途 可视区域即我们浏览网页的设备肉眼可见的区域,如下图 在日常开发中,我们经常需要判断目标元素是否在视窗之内或者和视窗的距离小于一个值(例如 100 px),从而实现一些常用的功能,例如: 图片 ...

  7. 国庆集训 Day1 复盘笔记

    9.25 \({\color{Green} \mathrm{A\ -\ Powered\ Addition}}\) 只要把序列扫一遍,然后求出目前最大值与当前值的差的最大值 \(x\),再 \(log ...

  8. GaussDB SQL查询语句执行过程解析

    本文分享自华为云社区<[GaussTech第2期]GaussDB SQL查询语句执行过程解析>,作者: GaussDB 数据库. SQL于关系型数据库而言,重要性不言而喻.就像一个乐团的指 ...

  9. HarmonyOS NEXT应用开发案例——二级联动

    介绍 本示例主要介绍了List组件实现二级联动(Cascading List)的场景. 该场景多用于短视频中拍摄风格的选择.照片编辑时的场景的选择. 效果图预览 使用说明: 滑动二级列表侧控件,一级列 ...

  10. 阿里云发布第四代神龙架构,提供业界首个大规模弹性RDMA加速能力

    ​简介:10月20日,2021年杭州云栖大会上,阿里云发布第四代神龙架构,升级至全新的eRMDA网络架构,是业界首个大规模弹性RDMA加速能力. 10月20日,2021年杭州云栖大会上,阿里云发布第四 ...