做网站的资金来源北京高端网站建设飞沐

news/2025/9/24 7:38:09/文章来源:
做网站的资金来源,北京高端网站建设飞沐,中装建设集团网站,客户信息管理软件这是我的第 54 篇原创文章。String 类型是我们使用最频繁的数据类型#xff0c;没有之一。那么提高 String 的运行效率#xff0c;无疑是提升程序性能的最佳手段。我们本文将从 String 的源码入手#xff0c;一步步带你实现字符串优化的小目标。不但教你如何有效的使用字符串… 这是我的第 54 篇原创文章。String 类型是我们使用最频繁的数据类型没有之一。那么提高 String 的运行效率无疑是提升程序性能的最佳手段。我们本文将从 String 的源码入手一步步带你实现字符串优化的小目标。不但教你如何有效的使用字符串还为你揭晓这背后的深层次原因。本文涉及的知识点如下图所示在看如何优化 String 之前我们先来了解一下 String 的特性毕竟知己知彼才能百战不殆。字符串的特性 想要了解 String 的特性就必须从它的源码入手如下所示// 源码基于 JDK 1.8 public final class Stringimplements java.io.Serializable, ComparableString, CharSequence {// String 值的实际存储容器private final char value[];public String() {this.value  .value;}public String(String original) {this.value  original.value;this.hash  original.hash;}// 忽略其他信息 } 从他的源码我们可以看出String 类以及它的 value[] 属性都被 final 修饰了其中 value[] 是实现字符串存储的最终结构而  final 则表示“最后的、最终的”。我们知道被 final 修饰的类是不能被继承的也就是说此类将不能拥有子类而被 final 修饰的变量即为常量它的值是不能被改变的。这也就说当 String 一旦被创建之后就不能被修改了。String 为什么不能被修改String 的类和属性 value[] 都被定义为 final 了这样做的好处有以下三点安全性当你在调用其他方法时比如调用一些系统级操作指令之前可能会有一系列校验如果是可变类的话可能在你校验过后它的内部的值又被改变了这样有可能会引起严重的系统崩溃问题所以迫使 String 设计为 final 类的一个重要原因就是出于安全考虑高性能String 不可变之后就保证的 hash 值的唯一性这样它就更加高效并且更适合做 HashMap 的 key- value 缓存节约内存String 的不可变性是它实现字符串常量池的基础字符串常量池指的是字符串在创建时先去“常量池”查找是否有此“字符串”如果有则不会开辟新空间创作字符串而是直接把常量池中的引用返回给此对象这样就能更加节省空间。例如通常情况下 String 创建有两种方式直接赋值的方式如 String strJava另一种是 new 形式的创建如 String str new String(Java)。当代码中使用第一种方式创建字符串对象时JVM 首先会检查该对象是否在字符串常量池中如果在就返回该对象引用否则新的字符串将在常量池中被创建。这种方式可以减少同一个值的字符串对象的重复创建节约内存。String str new String(Java) 这种方式首先在编译类文件时“Java”常量字符串将会放入到常量结构中在类加载时“Java”将会在常量池中创建其次在调用 new 时JVM 命令将会调用 String 的构造函数同时引用常量池中的“Java”字符串在堆内存中创建一个 String 对象最后 str 将引用 String 对象。1.不要直接字符串 通过上面的内容我们知道了 String 类是不可变的那么在使用 String 时就不能频繁的 字符串了。优化前代码public static String doAdd() {String result  ;for (int i  0; i  10000; i) {result  ( i:  i);}return result; } 有人可能会问我的业务需求是这样的那我该如何实现官方为我们提供了两种字符串拼加的方案StringBuffer 和 StringBuilder其中 StringBuilder 为非线程安全的而 StringBuffer 则是线程安全的StringBuffer 的拼加方法使用了关键字 synchronized 来保证线程的安全源码如下Override public synchronized StringBuffer append(CharSequence s) {toStringCache  null;super.append(s);return this; } 也因为使用 synchronized 修饰所以 StringBuffer 的拼加性能会比 StringBuilder 低。那我们就用 StringBuilder 来实现字符串的拼加优化后代码public static String doAppend() {StringBuilder sb  new StringBuilder();for (int i  0; i  10000; i) {sb.append( i:  i);}return sb.toString(); } 我们通过代码测试一下两个方法之间的性能差别public class StringTest {public static void main(String[] args) {for (int i  0; i  5; i) {// Stringlong st1  System.currentTimeMillis(); // 开始时间doAdd();long et1  System.currentTimeMillis(); // 开始时间System.out.println(String 拼加执行时间  (et1 - st1));// StringBuilderlong st2  System.currentTimeMillis(); // 开始时间doAppend();long et2  System.currentTimeMillis(); // 开始时间System.out.println(StringBuilder 拼加执行时间  (et2 - st2));System.out.println();}}public static String doAdd() {String result  ;for (int i  0; i  10000; i) {result  (Java中文社群:  i);}return result;}public static String doAppend() {StringBuilder sb  new StringBuilder();for (int i  0; i  10000; i) {sb.append(Java中文社群:  i);}return sb.toString();} } 以上程序的执行结果如下String 拼加执行时间429StringBuilder 拼加执行时间1String 拼加执行时间325StringBuilder 拼加执行时间1String 拼加执行时间287StringBuilder 拼加执行时间1String 拼加执行时间265StringBuilder 拼加执行时间1String 拼加执行时间249StringBuilder 拼加执行时间1从结果可以看出优化前后的性能相差很大。注意此性能测试的结果与循环的次数有关也就是说循环的次数越多他们性能相除的结果也越大。接下来我们要思考一个问题为什么 StringBuilder.append() 方法比 的性能高而且拼接的次数越多性能的差距也越大当我们打开 StringBuilder 的源码就可以发现其中的“小秘密”了StringBuilder 父类 AbstractStringBuilder 的实现源码如下abstract class AbstractStringBuilder implements Appendable, CharSequence {char[] value;int count;Overridepublic AbstractStringBuilder append(CharSequence s, int start, int end) {if (s  null)s  null;if ((start  0) || (start  end) || (end  s.length()))throw new IndexOutOfBoundsException(start   start  , end   end  , s.length()  s.length());int len  end - start;ensureCapacityInternal(count  len);for (int i  start, j  count; i  end; i, j)value[j]  s.charAt(i);count  len;return this;}// 忽略其他信息... } 而 StringBuilder 使用了父类提供的 char[] 作为自己值的实际存储单元每次在拼加时会修改 char[] 数组StringBuilder toString() 源码如下Override public String toString() {// Create a copy, dont share the arrayreturn new String(value, 0, count); } 综合以上源码可以看出StringBuilder 使用了 char[] 作为实际存储单元每次在拼加时只需要修改 char[] 数组即可只是在 toString() 时创建了一个字符串而 String 一旦创建之后就不能被修改因此在每次拼加时都需要重新创建新的字符串所以 StringBuilder.append() 的性能就会比字符串的 性能高很多。2.善用 intern 方法 善用 String.intern() 方法可以有效的节约内存并提升字符串的运行效率先来看 intern() 方法的定义与源码/** * Returns a canonical representation for the string object. * p * A pool of strings, initially empty, is maintained privately by the * class {code String}. * p * When the intern method is invoked, if the pool already contains a * string equal to this {code String} object as determined by * the {link #equals(Object)} method, then the string from the pool is * returned. Otherwise, this {code String} object is added to the * pool and a reference to this {code String} object is returned. * p * It follows that for any two strings {code s} and {code t}, * {code s.intern()  t.intern()} is {code true} * if and only if {code s.equals(t)} is {code true}. * p * All literal strings and string-valued constant expressions are * interned. String literals are defined in p 3.10.5 of the * citeThe Javatrade; Language Specification/cite. * * return  a string that has the same contents as this string, but is *          guaranteed to be from a pool of unique strings. */ public native String intern(); 可以看出 intern() 是一个高效的本地方法它的定义中说的是当调用 intern 方法时如果字符串常量池中已经包含此字符串则直接返回此字符串的引用如果不包含此字符串先将字符串添加到常量池中再返回此对象的引用。那什么情况下适合使用 intern() 方法Twitter 工程师曾分享过一个 String.intern() 的使用示例Twitter 每次发布消息状态的时候都会产生一个地址信息以当时 Twitter 用户的规模预估服务器需要 32G 的内存来存储地址信息。public class Location {private String city;private String region;private String countryCode;private double longitude;private double latitude; } 考虑到其中有很多用户在地址信息上是有重合的比如国家、省份、城市等这时就可以将这部分信息单独列出一个类以减少重复代码如下public class SharedLocation {private String city;private String region;private String countryCode; }public class Location {private SharedLocation sharedLocation;double longitude;double latitude; } 通过优化数据存储大小减到了 20G 左右。但对于内存存储这个数据来说依然很大怎么办呢Twitter 工程师使用 String.intern() 使重复性非常高的地址信息存储大小从 20G 降到几百兆从而优化了 String 对象的存储。实现的核心代码如下SharedLocation sharedLocation  new SharedLocation(); sharedLocation.setCity(messageInfo.getCity().intern());     sharedLocation.setCountryCode(messageInfo.getRegion().intern()); sharedLocation.setRegion(messageInfo.getCountryCode().intern()); 从 JDK1.7 版本以后常量池已经合并到了堆中所以不会复制字符串副本只是会把首次遇到的字符串的引用添加到常量池中。此时只会判断常量池中是否已经有此字符串如果有就返回常量池中的字符串引用。这就相当于以下代码String s1  new String(Java中文社群).intern(); String s2  new String(Java中文社群).intern(); System.out.println(s1  s2); 执行的结果为true此处如果有人问为什么不直接赋值使用 String s1 Java中文社群是因为这段代码是简化了上面 Twitter 业务代码的语义而创建的他使用的是对象的方式而非直接赋值的方式。更多关于 intern() 的内容可以查看《别再问我new字符串创建了几个对象了我来证明给你看》这篇文章。3.慎重使用 Split 方法 之所以要劝各位慎用 Split 方法是因为 Split 方法大多数情况下使用的是正则表达式这种分割方式本身没有什么问题但是由于正则表达式的性能是非常不稳定的使用不恰当会引起回溯问题很可能导致 CPU 居高不下。例如以下正则表达式String badRegex  ^([hH][tT]{2}[pP]://|[hH][tT]{2}[pP][sS]://)(([A-Za-z0-9-~]).)([A-Za-z0-9-~\\\\/])$; String bugUrl  http://www.apigo.com/dddp-web/pdf/download?request6e7JGxxxxx4ILd-kExxxxxxxqJ4-CHLmqVnenXC692m74H38sdfdsazxcUmfcOH2fAfY1Vw__%5EDadIfJgiEf; if (bugUrl.matches(badRegex)) {System.out.println(match!!); } else {System.out.println(no match!!); } 执行效果如下图所示可以看出此代码导致了 CPU 使用过高。Java 正则表达式使用的引擎实现是 NFANon deterministic Finite Automaton不确定型有穷自动机自动机这种正则表达式引擎在进行字符匹配时会发生回溯backtracking而一旦发生回溯那其消耗的时间就会变得很长有可能是几分钟也有可能是几个小时时间长短取决于回溯的次数和复杂度。为了更好地解释什么是回溯我们使用以下面例子进行解释text  abbc; regex  ab{1,3}c; 上面的这个例子的目的比较简单匹配以 a 开头以 c 结尾中间有 1-3 个 b 字符的字符串。NFA 引擎对其解析的过程是这样子的首先读取正则表达式第一个匹配符 a 和 字符串第一个字符 a 比较匹配上了于是读取正则表达式第二个字符读取正则表达式第二个匹配符 b{1,3} 和字符串的第二个字符 b 比较匹配上了。但因为 b{1,3} 表示 1-3 个 b 字符串以及 NFA 自动机的贪婪特性也就是说要尽可能多地匹配所以此时并不会再去读取下一个正则表达式的匹配符而是依旧使用 b{1,3} 和字符串的第三个字符 b 比较发现还是匹配上了于是继续使用 b{1,3} 和字符串的第四个字符 c 比较发现不匹配了此时就会发生回溯发生回溯后我们已经读取的字符串第四个字符 c 将被吐出去指针回到第三个字符串的位置之后程序读取正则表达式的下一个操作符 c然后再读取当前指针的下一个字符 c 进行对比发现匹配上了于是读取下一个操作符然后发现已经结束了。这就是正则匹配执行的流程和简单的回溯执行流程而上面的示例在匹配到“com/dzfp-web/pdf/download?request6e7JGm38jf.....”时因为贪婪匹配的原因所以程序会一直读后面的字符串进行匹配最后发现没有点号于是就一个个字符回溯回去了于是就会导致了 CPU 运行过高。所以我们应该慎重使用 Split() 方法我们可以用 String.indexOf() 方法代替 Split() 方法完成字符串的分割。如果实在无法满足需求你就在使用 Split() 方法时对回溯问题加以重视就可以了。总结 本文通过 String 源码分析发现了 String 的不可变特性以及不可变特性的 3 大优点讲解然后讲了字符串优化的三个手段不要直接 字符串、善用 intern() 方法和慎重使用 Split() 方法。并且通过 StringBuilder 的源码分析了解了 append() 性能高的主要原因以及正则表达式不稳定性导致回溯问题进入导致 CPU 使用过高的案例分析希望可以切实的帮助到你。最后的话原创不易如果觉得本文对你有用请随手点击一个「在看」这是对作者最大的支持与鼓励谢谢你。参考 鸣谢https://time.geekbang.org/column/article/97215https://blog.csdn.net/ityouknow/article/details/808513389个小技巧让你的 if else看起来更优雅别再问我 new 字符串创建了几个对象了我来证明给你看关注公众号发送”进群“老王拉你进读者群。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/915222.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

开源建站工具头条小程序

VSCode 配置 C++ 环境(Windows) 参考http://t.csdnimg.cn/27G0Z 1. 配置 C++ 编译器 首先需要安装 C++ 编译器。在 Windows 上,可以安装 MinGW 或者 Visual Studio;在 MacOS 上,可以安装 Clang 或者 Xcode;在 Linux 上,可以安装 GCC。 1.2 添加环境变量 将 mingw64…

小蜜蜂网站建设网站快照怎么做

扭线机属于线缆加工设备,线缆加工设备种类非常多。有用于网线绞合的单绞,双绞机等,有关单绞机相关算法介绍,大家可以查看专栏相关文章,有详细介绍,常用链接如下: 线缆行业单绞机控制算法&#…

平面设计案例网站wordpress cms布局

正题 评测记录:https://www.luogu.org/recordnew/lists?uid52918&pidP3435 大意 一个字符串,对于每个前缀,求复制一份放在末尾可以覆盖整个前缀的前缀,求所有的长度和。 解题思路 这道题如果暴力的话很简单,对于每个前缀每…

上传网站图片不显示自己建的网站如何百度搜索

观察者模式(Observer) 观察者模式(Observer)简介: 定义一个一对多的依赖关系,让多个观察者对象监听某个主题对象,当主题对象的状态发生改变时,主题对象则通知所有的观察者对象&#…

中国建设银行培训网站网站素材图

前置概念 偏差 指模型的预测值与真实值之间的差异,它反映了模型的拟合能力。 方差 指模型在不同的训练集上产生的预测结果的差异,它反映了模型的稳定性。 方差和偏差对预测结果所造成的影响 在机器学习中,我们通常希望模型的偏差和方差都…

宏润建设集团网站手机网页游戏排行榜前十名

文章目录 背景分析 问题来了比较一开始的情况解决方式 背景 之前有分析过一次类似问题,最终结论是在keyby之后,其中有一个key数量特别庞大,导致对应的subtask压力过大,进而使得整个job不再继续运作。在这个问题解决之后&#xff…

福建省高速公路建设管理网站软件开发工具和环境

重点 更多前端知识 诚邀各位前端从事者爱好者加入前端大佬技术交流社区,本社区主要分享技术栈、个人心得、技术交流、问题解惑等前端体系交流 点击下方文字加入 前端大佬技术交流社区 1. 函数的定义和调用 1.1 函数的定义方式 方式1 函数声明方式 function 关键…

包小盒设计网站wordpress手机版主题无效

简单工厂模式描述的是,通过类的继承关系,父类(工厂类)与子类(产品类),调用父类中的方法,实际干活儿的是子类中的方法;封装需求的不确定性,做出通用的编程&…

德阳网站建设优化阳朔到桂林北

2558. 从数量最多的堆取走礼物 原题地址: 力扣每日一题:从数量最多的堆取走礼物 给你一个整数数组 gifts ,表示各堆礼物的数量。每一秒,你需要执行以下操作: 选择礼物数量最多的那一堆。 如果不止一堆都符合礼物数量最…

开网站做代销好网站根目录 本地共享

jarsigner, keytool 这2个都是JDK的内置工具,在JDK的bin目录中可以找到, 下面是使用jarsigner给jar文件签名的5个步骤: 1. 使用java的jar工具创建JAR文件; # 将当前文件夹下的所有文件打包到myapp-1.0.jar文件中 后面的*为通配符, 也可以指定需要打包的jar中的文件或者文件夹…

苏州网站开发外包公司免费ppt模板下载公众号

应用场景 上一篇《Spring Cloud Stream消费失败后的处理策略(一):自动重试》介绍了默认就会生效的消息重试功能。对于一些因环境原因、网络抖动等不稳定因素引发的问题可以起到比较好的作用。但是对于诸如代码本身存在的逻辑错误等&#xff…

做网站公司哪家正规古楼角网站建设

2019独角兽企业重金招聘Python工程师标准>>> 由于最近用阿里云日志服务整合log4j,在配置com.aliyun.openservices.log.log4j.LoghubAppender需要设置一些参数,因为项目中有统一的配置文件,所以想要可以直接在log4j.xml中通过${}来…

2025年国家科技奖初评公布(科技发明奖)

微信视频号:sph0RgSyDYV47z6快手号:4874645212抖音号:dy0so323fq2w小红书号:95619019828B站1:UID:3546863642871878B站2:UID: 3546955410049087 添加图片注释,不超过 140 字(可选) 添加图片注释,不超过 140 …

做网站的收入上海平台网站建设

SQL Server横向扩展方案-SODA每次在提到SQL Server扩展性问题的时候,似乎很多的SQL Server DBA或者使用微软技术开发的朋友心里总是一整痛:SQL Server只能纵向的扩展(Scaling-Up),无法横向的扩展(Scaling-Out)。每次有人提到Oracle和SQL Serv…

wordpress替代广州网站优化公司

对于前端来说,2023 是非同寻常的一年。我们见证了争相抢占甚至是发明服务器端渲染(SSR)市场的热潮、AI 的不断进步、Web 渲染器和 JS 引擎的寒武纪大爆发、一大批有力的竞争者试图摧毁巨头的统治地位…… 在开始预测未来一年发展趋势之前&am…

推荐系统网站开发徐州做网站企业

本次以多台机器需部署zabbix客户端为例: 机器先做免密互信,ansible主机上执行ssh-keygen,一路回车,然后将公钥发送给需管理的主机: ssh-copy-id rootIP 1、编辑hosts文件,添加需配置的主机IP,并测试连通…

最好的自助建站系统wordpress forest

在上一节中,我们简单讲述了数据库和SQL的基本概念。 本节我们讲述一下环境搭建,为下一节讲表的基本操作做下铺垫。 环境搭建 具体到操作,我们就要准备一些环境了。如果不进行练习,我们学习的知识将很快被遗忘。 MySQL安装&…

大岭山镇仿做网站廊坊网站建设-纵横网络+网站

海龟编辑器是一款专为广大少儿打造的Python编辑器,该软件功能强大且使用便利,可以帮助孩子们以搭积木的方式来学习Python,并且支持Python代码和图形化积木的双向互相转译,不但可以有效提升孩子的学习兴趣,而且还能够降…

局网站建设招标深圳网站建设 卓

多Transformer的双向编码器表示法 Bidirectional Encoder Representations from Transformers,即Bert; 第二部分 探索BERT变体 从本章开始的诸多内容,以理解为目标,着重关注对音频相关的支持(如果有的话)…

html5手机app网站模板免费下载网络网页制作

我们在开发中经常会用到一些指定区域进行打印机打印,但是使用常规方式打印会将全部页面打印,当然相同都为打印,但是打印出来的内容并不是我们需要的东西,进行给大家分享如何设置打印机指定区域进行打印;该标签中的内容…