百度360必应搜狗淘宝本站头条
当前位置:网站首页 > 文章教程 > 正文

String 方法中 replace 和 replaceAll 详解

yund56 2025-03-18 23:46 10 浏览

前言

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

  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

相关推荐

如何在Office 中编辑 PDF?附详细化步骤

PDF很受欢迎,因为它能在不同的设备和操作系统上仍然保持原有格式。但是,这也意味着直接更改PDF文件比其他格式更难更复杂。值得庆幸的是,Microsoftoffice和UPDF帮你解决这一难题。一...

我的 Windows 装机必备软件清单

今天给大家分享下我的装机必备软件,都是用了好多年的软件神器。靠谱、好用、无广告,Windows电脑必备软件,收藏这一篇就够了!01.浏览器王者:Chromehttps://www.google.c...

Docnet Core 是一个轻量级、高性能的 .NET PDF 操作库

DocnetCore介绍DocnetCore是一个轻量级、高性能的.NETPDF操作库,依托于PDFium渲染引擎,提供强大的PDF文档解析、渲染、操作等功能。它完全支持.NET...

分享三款好用的PDF编辑软件,轻松处理PDF

作为一名需要经常和PDF文件打交道的工作者,我来分享一下几款好用的PDF编辑软件,并详细分析了它们的优缺点,希望能帮你找到合适的工具。1.AdobeAcrobatDC作为PDF格式的发明者,Ado...

PDF文档创建工具软件:novaPDF OEM 11.9 Build 432 for Windows

novaPDFOEM是一款实用高效的软件,从头开始设计,让您尽可能轻松地在应用程序中添加PDF打印功能。换句话说,这个实用程序是专门为应用程序开发人员设计的,可以直接在程序安装程序中集成为PDF打印...

线性表顺序存储结构求集合的并,交,补,差(源代码附上 超详细)

一:算法分析1)用数组A,B,C,E表示集合。假定A={1,3,4,5,6,7,9,10},  B={2,,3,4,7,8,10},E={1,2,3,4,5,6,7,8,9,10},  输入数组A...

分享一套SpringBoot开发博客系统源码,包含完整开发文档和视频

基本信息项目名称:eblog摘要:eblog是一个基于Springboot2.1.2开发的博客学习项目,为了让项目融合更多的知识点,达到学习目的,编写了详细的从0到1开发文档。主要学习包括:自定义Fr...

通达信指标合集〔源码齐全〕

很多朋友问到我哪款指标好用,这里我说一下,之所以有很多不同的指标是因为我们在针对不同的盘面情况的时候使用的指标是不同的,我给到的指标一般来讲就目前的环境来讲都是比较适合的,今天我就把我平时自己常用的指...

巅峰对决!Spring Boot VS .NET 6

SpringBoot和ASP.NETCore都是企业中流行的Web框架,对于喜欢C#的人会使用ASP.NETCore,而对于Java或Kotlin等基于JVM的语...

在asp.net core 中控制访问权限的方法

Intro#由于项目需要,需要在基于asp.netmvc的Web项目框架中做权限的控制,于是才有了这个权限控制组件,最初只是支持netframework,后来dotnetcore2.0...

ASP.NET是否无生存之地?

ASP.NET,这个已经很久的技术,总觉得已经被时代淘汰,我们公司是一个10人小公司,几个十年十五年的项目还是用ASP.NET开发的。这两年由于客户的需求变化,我们公司也顺势开始对这些项目重新开发,改...

Spring Boot + Vue.js 实现前后端分离(附源码)

作者:梁小生0101链接:juejin.im/post/5c622fb5e51d457f9f2c2381SpringBoot+Vue.js前后端涉及基本概念介绍,搭建记录,本文会列举出用到环...

ASP.NET Core 中的 Mapster 使用入门教程

在本文中,我们将学习如何在ASP.NETCore应用程序中使用Mapster。首先,我们将了解Mapster是什么以及如何将其安装到.NETCore应用程序中。然后,我们将在使用...

Asp.net常用方法及request和response-a

asp.net教程asp.net常用方法:1、Request.UrlReferrer请求的来源,可以根据这个判断从百度搜的哪个关键词、防下载盗链、防图片盗链,可以伪造(比如迅雷)。(使用全局一般处理...

ASP.NET Core使用功能开关控制路由访问

前言在前面的文章,我们介绍了使用Middleware有条件地允许访问路由(《ASP.NETCore使用Middleware有条件地允许访问路由》)。而对于一些试验性的功能,我们并不希望用密码去控制是...