String、StringBuffer、StringBuilder

server/2024/10/19 3:32:46/

String、StringBuffer、StringBuilder

String

 final class

    • 所有属性也都是 final 的
    • 原生的保证了基础线程安全
      • 因为无法对它内部数据进行任何修改

典型的 Immutable 类

    • 所以拼接、裁剪字符串等动作,都会产生新的 String 对象
      • 对应用性能有明显影响
      • 操作不当可能会产生大量临时字符串 

StringBuffer

可修改字符序列

    • StringBuffer 和 StringBuilder 底层都是利用可修改的(char,JDK 9 以后是 byte)数组
    • 继承了 AbstractStringBuilder

把各种修改数据的方法都加上 synchronized 关键字

    • 线程安全
      • 也随之带来了额外的性能开销
    • 简单粗暴

StringBuilder

可修改字符序列

    • 在能力上和 StringBuffer 基本相同
    • 继承了 AbstractStringBuilder

Java 1.5 中新增

    • 是绝大部分情况下进行字符串拼接的首选

线程不安全

    • 有效减小了开销

内部数组

内部数组的大小应该如何决定呢?

目前的实现

    • 构建时初始字符串长度加 16
      • 如果构建对象时没有输入最初的字符串
        • 初始值就是 16
      • 可以在创建时,主动指定合适的大小
    • 扩容会产生多重开销
      • 要抛弃原有数组,创建新的数组,还要进行 arraycopy

String的演化

在历史版本中,使用 char 数组保存数据

    • 非常直接
    • Java 中的 char 是两个 bytes 大小
      • 但拉丁语系语言的字符不需要太宽的 char
      • 这样无区别的实现就产生了一定的浪费

Compact Strings 

    • 将数据存储方式从 char 数组改变为一个 byte 数组加上一个标识编码的所谓 coder,并且将相关字符串操作类都进行了修改
    • 紧凑字符串
      • 更小的内存占用、更快的操作速度
    • 所有相关的 Intrinsic 之类也都进行了重写
      • 保证没有任何性能损失。
    • 这个特性对于绝大部分应用来说是透明的
      • 因为虽然底层实现发生了改变,但 Java 字符串的行为并没有大的变化,
      • 绝大部分情况不需要修改已有代码

字符串缓存

intern 机制

Intern 是一种显式地排重机制

    • Java的intern机制是指在运行时,如果一个字符串常量(即用双引号括起来的字符串字面量)已经存在于字符串池中,那么在创建新的该字符串常量时,会返回已存在的字符串常量的引用,而不是新创建一个对象。

 intern() 方法

    • 作用是提示 JVM 把相应字符串缓存起来,以备重复使用。
    • String 在 Java 6 以后提供
    • 创建字符串对象并调用 intern() 方法时
      • 如果字符串常量池中已经有缓存的字符串
        • 返回缓存里的实例
      • 如果没有
        • 将此String对象添加到池中缓存起来

早期的版本保存在 PermGen中

    •  PermGen也就是“永久代”
    • 这个空间是很有限的
    • 基本不会被 FullGC 之外的垃圾收集照顾到
    • 所以,如果使用不当,OOM 就会光顾。

后续版本中保存在堆中

    • 避免永久代占满的问题
      • 永久代在 JDK 8 中被 MetaSpace(元数据区)替代
    • 默认缓存大小也在不断地扩大中
      • -XX:+PrintStringTableStatistics
        • 查看默认缓存
      • -XX:StringTableSize=N
        • 调整默认缓存

G1 GC 下的字符串排重

在 Oracle JDK 8u20 之后,推出了这个新的特性

将相同数据的字符串指向同一份数据

    •  JVM 底层的改变,因此不需要修改 Java 类库

目前是默认关闭的

    • -XX:+UseStringDeduplication
      • 开启G1 GC 下的字符串排重功能

Intrinsic 机制

JVM 的底层优化机制

运行的往往就是特殊优化的本地代码,而不是 Java 代码生成的字节码

一种利用 native 方式 hard-coded 的逻辑

-XX:+PrintCompilation -XX:+UnlockDiagnosticVMOptions -XX:+PrintInlining

    • 查看 intrinsic 发生的状态

http://www.ppmy.cn/server/57068.html

相关文章

运维系列.Nginx中使用HTTP压缩功能

运维专题 Nginx中使用HTTP压缩功能 - 文章信息 - Author: 李俊才 (jcLee95) Visit me at CSDN: https://jclee95.blog.csdn.netMy WebSite:http://thispage.tech/Email: 291148484163.com. Shenzhen ChinaAddress of this article:https://blog.csdn.net/qq_28550…

使用Kubernetes部署Spring Boot应用的实践

使用Kubernetes部署Spring Boot应用的实践 大家好,我是微赚淘客系统3.0的小编,也是冬天不穿秋裤,天冷也要风度的程序猿! Kubernetes(简称K8s)是一个开源的容器编排引擎,广泛用于自动化部署、扩…

CosyVoice - 阿里最新开源语音克隆、文本转语音项目 支持情感控制及粤语 本地一键整合包下载

近日,阿里通义实验室发布开源语音大模型项目FunAudioLLM,而且一次包含两个模型:SenseVoice和CosyVoice。 CosyVoice专注自然语音生成,支持多语言、音色和情感控制,支持中英日粤韩5种语言的生成,效果显著优于…

VUE与React的生命周期对比

前言 在前端开发中,Vue和React是两个非常流行的JavaScript框架,它们各自有着独特的生命周期机制。了解并熟练掌握这些生命周期,对于开发高效、可维护的前端应用至关重要。本文将详细对比Vue和React的生命周期,帮助开发者更好地理…

【Selenium配置】WebDriver安装浏览器驱动(ChromeEdge)

【Selenium配置】WebDriver安装浏览器驱动(Chrome&Edge) 文章目录 【Selenium配置】WebDriver安装浏览器驱动(Chrome&Edge)Chrome确认Chrome版本下载对应driver把解压后的chromedriver文件放在chrome安装目录下&#xff0…

Qt实现检测软件是否多开

Qt实现检测软件是否多开 在桌面软件开发中,软件通常要设置只允许存在一个进程,像一些熟知的音乐软件,QQ音乐这种。而这些软件在限制只有一个进程的同时,通常还会有双击桌面图标唤醒已运行的后台进程的功能。关于双击桌面唤醒已运…

论文略读:Can Long-Context Language Models Subsume Retrieval, RAG, SQL, and More?

202406 arxiv 1 intro 传统上,复杂的AI任务需要多个专门系统协作完成。 这类系统通常需要独立的模块来进行信息检索、问答和数据库查询等任务大模型时代,尤其是上下文语言模型(LCLM)时代,上述问题可以“一体化”完成…

利用GPT 将 matlab 内置 bwlookup 函数转C

最近业务需要将 matlab中bwlookup 的转C 这个函数没有现成的m文件参考,内置已经打成库了,所以没有参考源代码 但是它的解释还是很清楚的,可以根据这个来写 Nonlinear filtering using lookup tables - MATLAB bwlookup - MathWorks 中国 A…