stringbuilder寻找字符串位置可能存在多个 java_Java 语言基础amp;String

Java 语言基础

String  

字符串的不可变性  

定义一个字符串

使用变量来赋值变量    

String s2 = s;  

s2 保存了相同的引用值, 因为他们代表同一个对象  

字符串连接  

s = s.concat("ef");  

s 中保存的是一个重新创建出来的 string 对象的引用  

总结

一旦一个 string 对象在内存(堆)中被创建出来, 他就无法被修改。特别要注意的是,String 类的所有方法都没有改变字符串本身的值, 都是返回了一个新的对象。

如果你需要一个可修改的字符串, 应该使用 StringBuffer 或者 StringBuilder。否则会有大量时间浪费在垃圾回收上, 因为每次试图修改都有新的 string 对象被创建出来  

JDK 6 和 JDK 7 中 substring 的原理及区别  

调用 substring()时发生了什么? 

你可能知道, 因为 x 是不可变的, 当使用 x.substring(1,3)对 x 赋值的时候, 它会指向一个全新的字符串: 

JDK 6 中的 substring  

String 是通过字符数组实现的。在 jdk 6 中, String 类包含三个成员变量:char value[], int offset, int count。他们分别用来存储真正的字符数组, 数组的第一个位置索引以及字符串中包含的字符个数。 

String 是通过字符数组实现的。在 jdk 6 中, String 类包含三个成员变量:char value[], int offset, int count。他们分别用来存储真正的字符数组, 数组的第一个位置索引以及字符串中包含的字符个数。

JDK 6 中的 substring 导致的问题    

如果你有一个很长很长的字符串, 但是当你使用 substring 进行切割的时候你只需要很短的一段。这可能导致性能问题, 因为你需要的只是一小段字符序列, 但是你却引用了整个字符串( 因为这个非常长的字符数组一直在被引用, 所以无法被回收, 就可能导致内存泄露) 。在 JDK 6 中, 一般用以下方式来解决该问题, 原理其实就是生成一个新的字符串并引用他。 

内存泄露:在计算机科学中, 内存泄漏指由于疏忽或错误造成程序未能释放已经不再使用的内存。内存泄漏并非指内存在物理上的消失, 而是应用程序分配某段内存后, 由于设计错误, 导致在释放该段内存之前就失去了对该段内存的控制, 从而造成了内存的浪费  

JDK 7 中的 substring  

上面提到的问题, 在 jdk 7 中得到解决。在 jdk 7 中, substring 方法会在堆内存中创建一个新的数组。 

以上是 JDK 7 中的 subString 方法, 其使用 new String 创建了一个新字符串, 避免对老字符串的引用。从而解决了内存泄露问题。

所以, 如果你的生产环境中使用的 JDK 版本小于 1.7, 当你使用 String 的 subString方法时一定要注意, 避免内存泄露。 

replaceFirst、 replaceAll、 replace 区别  

replace(CharSequence target, CharSequence replacement) , 用replacement 替换所有的 target, 两个参数都是字符串。

replaceAll(String regex, String replacement) , 用 replacement 替换所有的regex 匹配项, regex 很明显是个正则表达式, replacement 是字符串。

replaceFirst(String regex, String replacement) , 基本和 replaceAll 相同, 区别是只替换第一个匹配项。可以看到, 其中 replaceAll 以及 replaceFirst 是和正则表达式有关的, 而 replace 和正则表达式无关。 

http://www.51gjie.com/java/771.html  

String 对“ +” 的重载  

1、 String s = "a" + "b", 编译器会进行常量折叠(因为两个都是编译期常量, 编译期可知), 即变成 String s = "ab  

2、 对于能够进行优化的(String s = "a" + 变量 等)用 StringBuilder 的 append()方法替代, 最后调用 toString() 方法 (底层就是一个 new String())  

字符串拼接的几种方式和区别  

字符串不变性与字符串拼接  

其实, 所有的所谓字符串拼接, 都是重新生成了一个新的字符串。下面一段字符串拼接代码:String s = "abcd";s = s.concat("ef");其实最后我们得到的 s 已经是一个新的字符串了。 

使用+拼接字符串  

运算符重载:在计算机程序设计中, 运算符重载( 英语:operator overloading) 是多态的一种。运算符重载, 就是对已有的运算符重新进行定义, 赋予其另一种功能, 以适应不同的数据类型。 

语法糖:语法糖( Syntactic sugar), 也译为糖衣语法, 是由英国计算机科学家彼得· 兰丁发明的一个术语, 指计算机语言中添加的某种语法, 这种语法对语言的功能没有影响, 但是更方便程序员使用。语法糖让程序更加简洁, 有更高的可读性。 

Concat  

StringBuffer  

StringBuilder

StringUtils.join  

除了 JDK 中内置的字符串拼接方法, 还可以使用一些开源类库中提供的字符串拼接方法名, 如 apache.commons 中提供的 StringUtils 类, 其中的 join 方法可以拼接字符串。String wechat = "Hollis";String introduce = "每日更新 Java 相关技术文章";System.out.println(StringUtils.join(wechat, ",", introduce));  

以上就是比较常用的五种在 Java 种拼接字符串的方式, 那么到底哪种更好用呢?为什么 Java 开发手册中不建议在循环体中使用+进行字符串拼接呢? 

使用+拼接字符串的实现原理  

通过查看反编译以后的代码, 我们可以发现, 原来字符串常量在拼接过程中, 是将String 转成了 StringBuilder 后, 使用其 append 方法进行处理的。

那 么 也 就 是 说 , J a v a 中 的 + 对 字 符 串 的 拼 接 , 其 实 现 原 理 是 使 用StringBuilder.append    

concat 是如何实现的  

concat 方法的源代码  

这段代码首先创建了一个字符数组, 长度是已有字符串和待拼接字符串的长度之和, 再把两个字符串的值复制到新的字符数组中, 并使用这个字符数组创建一个新的 String 对象并返回。

通过源码我们也可以看到, 经过 concat 方法, 其实是 new 了一个新的 String, 这也就呼应到前面我们说的字符串的不变性问题上了。 

StringBuffer 和 StringBuilder  

append 会直接拷贝字符到内部的字符数组中, 如果字符数组长度不够, 会进行扩展。

StringBuffer 和 StringBuilder 类似, 最大的区别就是 StringBuffer 是线程安全的,看一下 StringBuffer 的 append 方法。 

StringUtils.join 是如何实现的  

通过查看 StringUtils.join 的源代码, 我们可以发现, 其实他也是通过 StringBuilder来实现的。 

效率比较  

从结果可以看出, 用时从短到长的对比是:StringBuilderStringBuffer 在 StringBuilder 的基础上, 做了同步处理, 所以在耗时上会相对多一些。

StringUtils.join 也是使用了 StringBuilder, 并且其中还是有很多其他操作, 所以耗时较长, 这个也容易理解。其实 StringUtils.join 更擅长处理字符串数组或者列表的拼接。

那么问题来了, 前面我们分析过, 其实使用+拼接字符串的实现原理也是使用的StringBuilder, 那为什么结果相差这么多, 高达 1000 多倍呢? 

我们可以看到反编译后的代码, 在 for 循环中, 每次都是 new 了一个 StringBuilder,然后再把 String 转成 StringBuilder, 再进行 append。而频繁的新建对象当然要耗费很多时间了, 不仅仅会耗费时间, 频繁的创建对象, 还会造成内存资源的浪费。

所以, Java 开发手册建议:循环体内, 字符串的连接方式, 使用 StringBuilder 的append 方法进行扩展。而不要使用+。 

总结

本文介绍了什么是字符串拼接, 虽然字符串是不可变的, 但是还是可以通过新建字符串的方式来进行字符串的拼接。常用的字符串拼接方式有五种, 分别是使用+、 使用 concat、 使用 StringBuilder、 使用 StringBuffer 以及使用 StringUtils.join。由于字符串拼接过程中会创建新的对象, 所以如果要在一个循环体中进行字符串拼接,就要考虑内存问题和效率问题。

因此, 经过对比, 我们发现, 直接使用 StringBuilder 的方式是效率最高的。因为StringBuilder 天生就是设计来定义可变字符串和字符串的变化操作的。但是, 还要强调的是:1、 如果不是在循环体中进行字符串拼接的话, 直接使用+就好了。2 、 如 果 在 并 发 场 景 中 进 行 字 符 串 拼 接 的 话 , 要 使 用 St r i n g B u f f e r 来 代 替StringBuilder。 

String.valueOf 和 Integer.toString 的区别  

String.valueOf 和 Integer.toString 的区别  

1.int i = 5;2.String i1 = "" + i;3.String i2 = String.valueOf(i);4.String i3 = Integer.toString(i);第三行和第四行没有任何区别, 因为 String.valueOf(i)也是调用 Integer.toString(i)来实现的。第二行代码其实是 String i1 = (new StringBuilder()).append(i).toString();, 首先创建一个 StringBuilder 对象, 然后再调用 append 方法, 再调用 toString 方法。 

字符串池  

在 JVM 中, 为了减少相同的字符串的重复创建, 为了达到节省内存的目的。会单独开辟一块内存, 用于保存字符串常量, 这个内存区域被叫做字符串常量池  

当代码中出现双引号形式( 字面量) 创建字符串对象时, JVM 会先对这个字符串进行检查, 如果字符串常量池中存在相同内容的字符串对象的引用, 则将这个引用返回;否则,创建新的字符串对象, 然后将这个引用放入字符串常量池, 并返回该引用  

这种机制, 就是字符串驻留或池化  

字符串常量池的位置  

在 JDK 7 以前的版本中, 字符串常量池是放在永久代中的。

因为按照计划, JDK 会在后续的版本中通过元空间来代替永久代, 所以首先在 JDK7 中, 将字符串常量池先从永久代中移出, 暂时放到了堆内存中。在 JDK 8 中, 彻底移除了永久代, 使用元空间替代了永久代, 于是字符串常量池再次从堆内存移动到永久代中  

Class 常量池  

谈到常量池, 在 Java 体系中, 共用三种常量池。分别是字符串常量池、 Class 常量池和运行时常量池。 

Class 常量池可以理解为是 Class 文件中的资源仓库。Class 文件中除了包含类的版本、 字段、 方法、 接口等描述信息外, 还有一项信息就是常量池(constant pool table),用于存放编译器生成的各种字面量(Literal)和符号引用(Symbolic References)。 

常量池中有什么  

字面量  

用于表达源代码中一个固定值的表示法( notation)  

字面量只可以右值出现, 所谓右值是指等号右边的值, 如:int a=123 这里的 a 为左值, 123 为右值。在这个例子中 123 就是字面量  

符号引用  

符号引用是编译原理中的概念, 是相对于直接引用来说的。主要包括了以下三类常量:* 类和接口的全限定名 * 字段的名称和描述符 * 方法的名称和描述符  

Class 常量池有什么用  

Class 常量池是 Class 文件中的资源仓库, 其中保存了各种常量。而这些常量都是开发者定义出来, 需要在程序的运行期使用的  

Class 是用来保存常量的一个媒介场所, 并且是一个中间场所。在 JVM 真的运行时, 需要把常量池中的常量加载到内存中  

运行时常量池  

它包括了若干种不同的常量:从编译期可知的数值字面量到必须运行期解析后才能获得的方法或字段引用。运行时常量池扮演了类似传统语言中符号(SymbolTable)的角色,不过它存储数据范围比通常意义上的符号表要更为广泛  

每一个运行时常量池都分配在 Java 虚拟机的方法区之中, 在类和接口被加载到虚拟机后, 对应的运行时常量池就被创建出来  

intern  (运行时)

在 JVM 中, 为了减少相同的字符串的重复创建, 为了达到节省内存的目的。会单独开辟一块内存, 用于保存字符串常量, 这个内存区域被叫做字符串常量池。 

intern 的功能很简单:在每次赋值的时候使用 String 的 intern 方法, 如果常量池中有相同值, 就会重复使用该对象, 返回对象引用。 

String 的长度限制  

那么, 明明 String 的构造函数指定的长度是可以支持 2147483647(2^31 - 1)的, 为什么像以上形式定义的时候无法编译呢?其实, 形如 String s = "xxx";定义 String 的时候, xxx 被我们称之为字面量, 这种字面量在编译之后会以常量的形式进入到 Class 常量池  

常量池限制  

字符串有长度限制, 在编译期, 要求字符串常量池中的常量不能超过 65535, 并且在javac 执行过程中控制了最大值为 65534。在运行期, 长度不能超过 Int 的范围, 否则会抛异常  

运行期限制  

前面提到的这种 String 长度的限制是编译期的限制, 也就是使用 String s= “ ” ;这种字面值方式定义的时候才会有的限制。

那么。String 在运行期有没有限制呢, 答案是有的, 就是我们前文提到的那个 Integer.MAX_VALUE , 这个值约等于 4G, 在运行期, 如果 String 的长度超过这个范围, 就可能会抛出异常  

总结

字符串有长度限制, 在编译期, 要求字符串常量池中的常量不能超过 65535, 并且在javac 执行过程中控制了最大值为 65534。在运行期, 长度不能超过 Int 的范围, 否则会抛异常。

最后, 这个知识点 , 我录制了视频(https://www.bilibili.com/video/BV1uK4y1t7H1/),

其中有关于如何进行实验测试、如何查阅 Java 规范以及如何对 javac 进行 deubg 的技巧。欢迎进一步学习。 

这是笔记!

作者 Hollis:https://github.com/hollischuang

cae121ae402acc865fa2bec65c0433aa.png

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

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

相关文章

cogs 547:[HAOI2011] 防线修建

★★★☆ 输入文件:defense.in 输出文件:defense.out 简单对比                      时间限制:1 s 内存限制:128 MB 题目描述: 近来A国和B国的矛盾激化,为了预防不测&#…

人工智能和计算机软件,人工智能在计算机软件方面有什么应用?

人工智能(Artificial Intelligence) ,英文缩写为AI。它是研究、开发用于模拟、延伸和扩展人的智能的理论、方法、技术及应用系统的一门新的技术科学。人工智能是计算机科学的一个分支,它企图了解智能的实质,并生产出一种新的能以人类智能相似…

pq分解法中b’怎么求_14.初中数学:二元一次方程组,加减消元法怎么解?视频有详细解题步骤...

欢迎您来到方老师数学课堂,请点击上方蓝色字体,关注方老师数学课堂。所有的视频内容,全部免费,请大家放心关注,放心订阅。初中数学:二元一次方程组,加减消元法怎么解?视频有详细解题…

win8计算机可用内存不足,Win8.1玩游戏提示计算机内存不足,Win8.1内存不足怎么办?...

Win8.1玩游戏提示计算机内存不足,Win8.1内存不足怎么办?有朋友使用Win8.1系统,这一段时间,在玩游戏(如孤岛危机3、鬼泣4)过程中,频繁出现下面提示框:关闭程序以防止信息丢失计算机的内存不足。请保存文件并关闭这些程序Windows将…

css划上去变长,Css3如何实现鼠标移上变长特效?(图文+视频)

本篇文章主要给大家介绍用css3实现鼠标移入变长效果的方法。在前端页面设计中,css的功能是异常强大的,只要运用好它,你能实现很多网站各种精彩的动态效果。那么在之前的文章中也给大家分享介绍了一些用css实现动画效果的方法,比如…

小米路由器怎么连接无盘服务器,播放器+服务器的方法瞬间玩转小米路由方法图文介绍...

“厨具”:小米路由及其外接硬盘、安卓手机、威动播放器(VidOn Player)、威动服务器(VidOn Server)“食材”:冰雪奇缘、生活大爆炸用两种方法将其“熬制”,时间短、内容丰富,“营养价值”相当的高。一、将小米路由作为NAS&#xff…

统计源期刊目录_统计源期刊是什么意思

统计源期刊是什么意思?统计源期刊全称中国科技论文统计源期刊,也就是我们常说的科技核心期刊,科技核心期刊是我国核心期刊体系中的一类,在国内个人评职晋升、学术评估中占据着重要地位,统计源期刊也是根据期刊多方面指…

ajax 请求post和get,ajax请求get和post

ajax请求get和post 内容精选换一换正常返回值类型说明200OKGET、PUT、POST操作正常返回204No ContentDELETE操作正常返回异常返回值说明400 Bad Request服务器未能处理请求。401 Unauthorized被请求的页面需要用户名和密码。403 Forbidden对被请求页面的访问被禁止。404 Not Fo…

网页底部的版权信息_Shopify底部的版权信息(Powered by Shopify )如何删除

大多数新的Shopify商店所有者通常在一开始就遇到一个小问题。他们通常想摆脱商店页脚中的“Powered by Shopify”文本/链接。Shopify提供支持的含义是什么?Shopify是一个电子商务平台,可帮助创建和自定义电子商务商店。当您在此平台上创建商店时&#xf…

ftp 服务器 文件 连接 导出,ftp 服务器 文件 连接 导出

ftp 服务器 文件 连接 导出 内容精选换一换“数据导入”章节适用于MRS 3.x及后续版本。Loader是实现MRS与外部数据源如关系型数据库、SFTP服务器、FTP服务器之间交换数据和文件的ETL工具,支持将数据或文件从关系型数据库或文件系统导入到MRS系统中。Loader支持如下数…

多个虚拟主机服务器,Windows多个虚拟主机服务器

Windows多个虚拟主机服务器 内容精选换一换迁移前,您需要设置目的端服务器。该目的端用来接收源端的数据,同时您也可以使用该目的端进行迁移测试和启动目的端。只有“迁移阶段”为“已就绪”时才可设置目的端。或单击“操作”列的“更多 > 设置目的端…

armv8 汇编 绝对地址赋值_详解汇编语言B和LDR指令与相对跳转和绝对跳转的关系...

[TOC]为什么要有相对跳转和绝对跳转?顺序执行:指令一条一条按照顺序往下执行,比如变量的定义和赋值都是按照顺序执行的。跳转执行:当指令执行到当前位置后跳转到其他位置执行。比如,在主函数中调用其他函数就是典型的跳…

mongodb3.0 性能測试报告 一

mongodb3.0 性能測试报告 一 mongodb3.0 性能測试报告 二 mongodb3.0 性能測试报告 三測试环境: 服务器:X86 pcserver 共6台 cpu: 单颗8核 内存:64G 磁盘: raid 10 操作系统 :centos 6.5 mongo…

HTTP 错误 404.3 – Not Found 由于扩展配置问题而无法提供您请求的页面。如果该页面是脚本,请添加处理程序。如果应下载文件,请添加 MIME 映射。...

今天,在vs2013中新建了一个placard.json文件,当我用jq读取它的时候,去提示404,直接在浏览器访问这个文件,提示: HTTP 错误 404.3 – Not Found 由于扩展配置问题而无法提供您请求的页面。如果该页面是脚本&…

ArcGIS将CAD等高线转换为TIN/DEM数据

1.CAD图层分离 CAD快捷命令QSELECT(快速选择) 选择DGX,GCD图层,复制到新的CAD文件中 2.在ArcGIS中,将dwg文件转化为可编辑的要素类文件(shapefiles) 分析工具-提取分析-筛选 3.高程数据修正 鼠标右键生…

字节跳动专家会_字节跳动招聘直播策略运营专家/经理/海外财务AR BP,ACCA优先...

字节跳动是把人工智能技术大规模应用于信息分发的公司,短短7年,从最初的一个“今日头条”,已经发展为拥有“抖音”、“西瓜视频”、“火山小视频”、“FaceU”等十几款产品的公司。每天,都有6亿用户通过字节跳动的产品看见更大的世…

矩形河道中心排放污染物浓度点源二维移流扩散MATLAB解析解计算

某非可降解物质在20℃水体中从河道中心排放,速度与水流流速方向相同,排污口为时间连续点源。河道为矩形河道,长度16.0m,宽度3.0m,水深2.0m,水流流速2.0m/s。单位时间投放的污染物强度为30mg/L。假设污染物排…

ArcGIS如何将经纬度坐标显示转化为xy坐标显示

GIS中经纬度坐标显示如图: 视图-数据框属性-常规-显示(米) 点击确定,然后坐标显示就转换为xy坐标了 注意,以上设置只是设置了当前文档的坐标系统,并不是数据的坐标系 举个例子:我将2160这条等高…

ArcGIS改变数据集或要素类的的坐标系(投影)

数据管理工具-投影和变换-投影-输入数据集或要素类-输出数据集或要素类-输出坐标系(选择合适的投影坐标系)

地形图如何转换为数字高程模型(DEM)

1.设置参考坐标信息 一般的地形图没有坐标参考,在ArcCatalog 10.7中打开地形图,右键属性-空间参考-编辑,选择对应的空间参考坐标信息。 2..地图配准 将地形图在ArcMap中打开,一般地形图四角都有经纬度坐标信息,即通过…