百度360必应搜狗淘宝本站头条
当前位置:网站首页 > 技术分类 > 正文

String 方法中 replace 和 replaceAll 详解

ztj100 2024-12-05 18:08 25 浏览 0 评论

前言

我们先做一个简单的概述:

  1. replace() 和 replaceAll() 都是常用的替换字符串的方法;
  2. 两者都是全部替换,可以把源字符串中的某一字符或字符串全部换成指定的字符或字符串;
  3. 如果只想替换第一次出现的,可以使用 replaceFirst();
  4. 这个方法也是基于规则表达式的替换,但与replaceAll()不同的是,只替换第一次出现的字符串;
  5. replaceAll() 和 replaceFirst() 所用的替换参数可以是普通字符串,也可以是正则表达式;
  6. 如果 replaceAll() 和 replaceFirst() 所用的参数据不是基于规则表达式的,那么它们与 replace() 替换字符串的效果、效率是一样的。

注意:执行了替换操作后,返回一个新的对象,源字符串的内容是没有发生改变的。

源码分析

来看看源码中关于两个方法的定义,我分别摘取了一段:

* String.class */
...
/** 
 * Replaces each substring of this string that matches the literal target sequence 
 * with the specified literal replacement sequence ...
 * 翻译:用指定的文字替换序列替换与文字目标序列匹配的字符串的每个子字符串。
 */
public String replace(CharSequence target, CharSequence replacement) {
	return Pattern.compile(target.toString(),Pattern.LITERAL).
		matcher(this).replaceAll(Matcher.quoteReplacement(replacement.toString()));
    }
...

/** 
 * Replaces each substring of this string that matches the given regular expression 
 * with the given replacement...
 * 翻译:将与给定正则表达式匹配的字符串的每个子字符串替换为给定的替换。
 */
public String replaceAll(String regex, String replacement) {
	return Pattern.compile(regex).
		matcher(this).replaceAll(replacement);
}
...

通过方法的定义,我们发现:replaceAll() 在定义它的时候,就被赋予可以匹配正则表达式的功能。 通过源码,可以总结两点:

  1. String.replace() 和 String.replaceAll() 调用的方法是一样的,都是Matcher.replaceAll() 方法;
  2. replaceAll() 方法没有传入参数 “Pattern.LITERAL”;

就是这一点点的不同,决定了 replaceAll() 方法需要优先判断被替换的参数 regex 是不是一个正则表达式。

  • 如果是正则,执行正则替换;
  • 如果是字符串,执行字符串替换,此时和 replace() 就是一样的了。

replaceAll() 源码分析

我知道学技术的小伙伴都属于“刨根问底”栏目组的,下面我带大家看一看,参数 "Pattern.LITERAL"是怎么影响业务逻辑的:

1. String.replaceAll(String regex, String replacement) 函数如下:

它共调用了三个函数,作用分别是:

  • Pattern.compile(String regex) – 编译(解析)正则表达式,获得Pattern对象;
  • Pattern.matcher(CharSequence input) – 获取匹配器;
  • Matcher.replaceAll(String replacement) – 替换字符串;

顾名思义,我们需要解释的重点,就在 Pattern.compile(String regex) 方法中。

2. Pattern.compile(String regex) 函数如下:

它返回的是一个Pattern对象。

3. Pattern的构造函数如下:

这个构造函数是 private 级别的,不能被其他类直接调用,只能通过 Pattern 类的 compile(String regex) 和 compile(String regex, int flags) 调用。 该构造函数调用了 compile(),对 regex 参数的处理就发生在这个函数里面!!

4. Pattern.compile()函数如下:

其中:

  • ①中的参数"LITERAL"就是我们上面提到的那一点点不用(不清楚的可以再回看一下);
  • ①处的 if – else 语句,决定②处是否执行;
  • ②处的 matchRoot = expr(lastAccept);就是获得正则表达式匹配根结点的方法,若执行此方法,则开始进行正则表达式的匹配。

好了,再往下的代码我就不再演示了,有兴趣的小伙伴可以自己看一看。

代码论证

说了很多理论的东西,写几行代码验证下:

@Test
public void replaceTest() {
    String str1 = "Aoc.Iop.Aoc.Iop.Aoc";	    //定义三个一样的字符串
    String str2 = "Aoc.Iop.Aoc.Iop.Aoc";
    String str3 = "Aoc.Iop.Aoc.Iop.Aoc";

    String str11 = str1.replace(".", "#");	    // str11 = "Aoc#Iop#Aoc#Iop#Aoc"
    String str22 = str2.replaceAll(".", "#");	    // str22 = "###################"
    String str33 = str3.replaceFirst(".", "#");	    // str33 = "#oc.Iop.Aoc.Iop.Aoc"
}

由于“.”属于正则表达式的符号,所以 replaceAll() 方法执行的是正则替换。

转义符号 – “\”,需要格外注意下:

  • “\” 在 java 中是一个转义字符,所以需要用两个代表一个。 例如 System.out.println(“\\”);只打印出一个 “\”;
  • “\”也是正则表达式中的转义字符(replaceAll()的参数就是正则表达式),也需要用两个代表一个。 所以:“\\\\”会被j ava 转换成 “\\”,“\\” 又会被正则表达式转换成“\”。

看一个例子:

@Test
public void replaceTest() {
    String str1 = "blog.csdn.net/weixin_44259720/";
    String str2 = "blog.csdn.net/weixin_44259720/";
	    	
    String str11 = str1.replace("/", "\\");		// 转义
    String str22 = str2.replaceAll("/", "\\\\");	// 转义 + 正则匹配
}
	
输出结果相同:
    str11 = "blog.csdn.net\weixin_44259720\"
    str22 = "blog.csdn.net\weixin_44259720\"

小结

  1. replace 的参数是 char 和 CharSequence,即可以支持字符的替换,也支持字符串的替换(CharSequence 即字符串序列的意思,说白了也就是字符串);
  2. replaceAll 的参数是 regex,即基于正则表达式的替换。比如,可以通过 replaceAll ("\d", “*”) 把一个字符串所有的数字字符都换成星号;
  3. String 类执行了替换操作后,返回一个新的对象,源字符串的内容是没有发生改变的。

作者:IT无知君
链接:https://juejin.cn/post/7020951662546124837

相关推荐

电脑装系统用GHOST好,还是原装版本好?老司机都是这么装的

Hello大家好,我是兼容机之家的咖啡。安装Windows系统是原版ISO好还是ghost好呢?针对这个的问题,我们先来科普一下什么是ghost系统,和原版ISO镜像两者之间有哪些优缺点。如果是很了解...

苹果 iOS 14.5.1/iPadOS 14.5.1 正式版发布

IT之家5月4日消息今日凌晨,苹果发布了iOS14.5.1与iPadOS14.5.1正式版更新。这一更新距iOS14.5正式版发布过去了一周时间。IT之家了解到,苹果表示,...

iOS 13.1.3 正式版发布 包含错误修复和改进

苹果今天发布了iOS13.1.3和iPadOS13.1.3,这是iOS13发布之后第四个升级补丁。iOS13.1.2两周前发布。iOS13.1.3主要包括针对iPad和...

还不理解 Error 和 Exception 吗,看这篇就够了

在Java中的基本理念是结构不佳的代码不能运行,发现错误的理想时期是在编译期间,因为你不用运行程序,只是凭借着对Java基本理念的理解就能发现问题。但是编译期并不能找出所有的问题,有一些N...

Linux 开发人员发现了导致 MacBook“无法启动”的 macOS 错误

“多个严重”错误影响配备ProMotion显示屏的MacBookPro。...

启动系统时无法正常启动提示\windows\system32\winload.efi

启动系统时无法正常启动提示\windows\system32\winload.efi。该怎么解决?  最近有用户遇到了开机遇到的问题,是Windows未能启动。原因可能是最近更改了硬件或软件。虽然提...

离线部署之两种构建Ragflow镜像的方式,dify同理

在实际项目交付过程中,经常遇到要离线部署的问题,生产服务器无法连接外网,这时就需要先构建好ragflow镜像,然后再拷到U盘或刻盘,下面介绍两种构建ragflow镜像的方式。性能测试(网络情况好的情况...

Go语言 error 类型详解(go语言 异常)

Go语言的error类型是用于处理程序运行中错误情况的核心机制。它通过显式的返回值(而非异常抛出)来管理错误,强调代码的可控性和清晰性。以下是详细说明及示例:一、error类型的基本概念内置接口...

Mac上“闪烁的问号”错误提示如何修复?

现在Mac电脑的用户越来越多,Mac电脑在使用过程中也会出现系统故障。当苹果电脑无法找到系统软件时,Mac会给出一个“闪烁的问号”的标志。很多用户受到过闪烁问号这一常见的错误提示的影响,如何解决这个问...

python散装笔记——177 sys 模块(python sys模块详解)

sys模块提供了访问程序运行时环境的函数和值,例如命令行参数...

30天自制操作系统:第一天(30天自制操作系统电子书)

因为咱们的目的是为了研究操作系统的组成,所以直接从系统启动的第二阶段的主引导记录开始。前提是将编译工具放在该文件目录的同级目录下,该工具为日本人川合秀实自制的编译程序,优化过的nasm编译工具。...

五大原因建议您现在不要升级iOS 13或iPadOS

今天苹果放出了iPadOS和iOS13的公测版本,任何对新版功能感兴趣的用户都可以下载安装参与测试。除非你想要率先体验Dark模式,以及使用AppleID来登陆Facebook等服务,那么外媒CN...

Python安装包总报错?这篇解决指南让你告别pip烦恼!

在Python开发中,...

苹果提供了在M1 Mac上修复macOS重装错误的方案

#AppleM1芯片#在苹果新的M1Mac推出后不久,我们看到有报道称,在这些机器上恢复和重新安装macOS,可能会导致安装错误,使你的Mac无法使用。具体来说,错误信息如下:"An...

黑苹果卡代码篇三:常见卡代码问题,满满的干货

前言...

取消回复欢迎 发表评论: