咦,拆分个字符串都这么讲究?

来源 | 沉默王二

封图 | CSDN 付费下载于视觉中国

提到拆分字符串,我猜你十有八九会撂下一句狠话,“这有什么难的,直接上 String 类的 split() 方法不就拉到了!”假如你真的这么觉得,那可要注意了,事情远没这么简单。

来来来,搬个小板凳坐下。

假如现在有这样一串字符“沉默王二,一枚有趣的程序员”,需要按照中文的逗号“,”进行拆分,这意味着第一串字符为逗号前面的“沉默王二”,第二串字符为逗号后面的“一枚有趣的程序员”(这不废话)。另外,在拆分之前,要先进行检查,判断一下这串字符是否包含逗号,否则应该抛出异常。

public class Test {public static void main(String[] args) {String cmower = "沉默王二,一枚有趣的程序员";if (cmower.contains(",")) {String [] parts = cmower.split(",");System.out.println("第一部分:" + parts[0] +" 第二部分:" + parts[1]);} else {throw new IllegalArgumentException("当前字符串没有包含逗号");}}
}

这段代码看起来挺严谨的,对吧?程序输出的结果完全符合预期:

第一部分:沉默王二 第二部分:一枚有趣的程序员

这是建立在字符串是确定的情况下,最重要的是分隔符是确定的。否则,麻烦就来了。

大约有 12 种英文特殊符号,如果直接拿这些特殊符号替换上面代码中的分隔符(中文逗号),这段程序在运行的时候就会出现以下提到的错误。

  • 反斜杠 \(ArrayIndexOutOfBoundsException)

  • 插入符号 ^(同上)

  • 美元符号 $(同上)

  • 逗点 .(同上)

  • 竖线 |(正常,没有出错)

  • 问号 ?(PatternSyntaxException)

  • 星号 *(同上)

  • 加号 +(同上)

  • 左小括号或者右小括号 ()(同上)

  • 左方括号或者右方括号 [](同上)

  • 左大括号或者右大括号 {}(同上)

看到这,可能有小伙伴会说,“这不是钻牛角尖嘛”,不不不,做技术就应该秉持严谨的态度,否则,老大会给你的绩效打低分的——奖金拿得少,可不是好滋味。

那遇到特殊符号该怎么办呢?上正则表达式呗。

正则表达式是一组由字母和符号组成的特殊文本,它可以用来从文本中找出满足你想要的格式的句子。

那可能又有小伙伴说,“正则表达式那么多,我记不住啊!”别担心,我已经替你想好对策了。

下面这个链接是 GitHub 上学习正则表达式的一个在线文档,非常详细。遇到正则表达式的时候,掏出这份手册就完事了。记不住那么多正则表达式没关系啊,活学活用呗。

https://github.com/cdoco/learn-regex-zh

除了这份文档,还有一份:

https://github.com/cdoco/common-regex

作者收集了一些在平时项目开发中经常用到的正则表达式,可以直接拿来用,妙啊。

解决了心病之后,我们来用英文逗点“.”来替换一下分隔符:

String cmower = "沉默王二.一枚有趣的程序员";
if (cmower.contains(".")) {String [] parts = cmower.split("\\.");System.out.println("第一部分:" + parts[0] +" 第二部分:" + parts[1]);
}

在使用 split() 方法的时候,就需要使用正则表达式 \\. 来替代特殊字符英文逗点“.”了。为什么用两个反斜杠呢?因为它本身就是一个特殊字符,需要先转义。

也可以使用字符类 [] 来包含英文逗点“.”,它也是一个正则表达式,用来匹配方括号中包含的任意字符。

cmower.split("[.]");

除此之外, 还可以使用 Pattern 类的 quote() 方法来包裹英文逗点“.”,该方法会返回一个使用 \Q\E 包裹的字符串。

此时,String.split() 方法的使用示例如下所示:

String [] parts = cmower.split(Pattern.quote("."));

当通过调试模式进入 String.split() 方法源码的话,会发现以下细节:

<div class="output_wrapper" id="output_wrapper_id"><p><code>
return Pattern.compile(regex).split(this, limit);</code> </p></div>

String 类的 split() 方法调用了 Pattern 类的 split() 方法。也就意味着,我们拆分字符串有了新的选择,可以不使用 String 类的 split() 方法了。

public class TestPatternSplit {/*** 使用预编译功能,提高效率*/private static Pattern twopart = Pattern.compile("\\.");public static void main(String[] args) {String [] parts = twopart.split("沉默王二.一枚有趣的程序员");System.out.println("第一部分:" + parts[0] +" 第二部分:" + parts[1]);}
}

除此之外,还可以使用 Pattern 配合 Matcher 类进行字符串拆分,这样做的好处是可以对要拆分的字符串进行一些严格的限制,来看一段示例代码:

public class TestPatternMatch {/*** 使用预编译功能,提高效率*/private static Pattern twopart = Pattern.compile("(.+)\\.(.+)");public static void main(String[] args) {checkString("沉默王二.一枚有趣的程序员");checkString("沉默王二.");checkString(".一枚有趣的程序员");}private static void checkString(String str) {Matcher m = twopart.matcher(str);if (m.matches()) {System.out.println("第一部分:" + m.group(1) + " 第二部分:" + m.group(2));} else {System.out.println("不匹配");}}
}

这时候,正则表达式为 (.+)\\.(.+),意味着可以把字符串按照英文逗点拆分成一个字符组,英文小括号 () 的作用就在于此(可以查看我之前提供的正则表达式手册)。

由于模式是确定的,所以可以把 Pattern 表达式放在 main() 方法外面,通过 static 的预编译功能提高程序的效率。

来看一下程序的输出结果:

第一部分:沉默王二 第二部分:一枚有趣的程序员
不匹配
不匹配

不过,使用 Matcher 来匹配一些简单的字符串时相对比较沉重一些,使用 String 类的 split() 仍然是首选,因为该方法还有其他一些牛逼的功能。

比如说,你想把分隔符包裹在拆分后的字符串的第一部分,可以这样做:

String cmower = "沉默王二,一枚有趣的程序员";
if (cmower.contains(",")) {String [] parts = cmower.split("(?<=,)");System.out.println("第一部分:" + parts[0] +" 第二部分:" + parts[1]);
}

程序输出的结果如下所示:

第一部分:沉默王二, 第二部分:一枚有趣的程序员

可以看到分隔符“,”包裹在了第一部分,如果希望包裹在第二部分,可以这样做:

String [] parts = cmower.split("(?=,)");

可能有些小伙伴很好奇,?<= 和 ?= 是什么东东啊?它其实是正则表达式中的断言模式。

温馨提醒:如果对断言模式比较生疏的话,可以查看我之前提供的正则表达式手册。

另外,假如说字符串中包含了多个分隔符,而我们只需要 2 个的话,还可以这样做:

String cmower = "沉默王二,一枚有趣的程序员,宠爱他";
if (cmower.contains(",")) {String [] parts = cmower.split(",", 2);System.out.println("第一部分:" + parts[0] +" 第二部分:" + parts[1]);
}

split() 方法可以传递 2 个参数,第一个为分隔符,第二个为拆分的字符串个数。查看该方法源码的话,你就可以看到以下内容:

直接 substring() 到原字符串的末尾,也就是说,第二个分隔符处不再拆分。然后就 break 出循环了。来看一下程序输出的结果:

第一部分:沉默王二 第二部分:一枚有趣的程序员,宠爱他

好了,亲爱的读者朋友,以上就是本文的全部内容了。是不是突然感觉拆分个字符串真的挺讲究的?

 

推荐阅读

  • 一文带你认识keepalived,再带你通关LVS+Keepalived!

  • 那个分分钟处理 10 亿节点图计算的 Plato,现在怎么样了?

  • “谷歌杀手”发明者,科学天才 Wolfram

  • 数据库激荡 40 年,深入解析 PostgreSQL、NewSQL 演进历程

  • 超详细!一文告诉你 SparkStreaming 如何整合 Kafka !附代码可实践

  • 5分钟!就能学会以太坊 JSON API 基础知识!

    真香,朕在看了!

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

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

相关文章

linux-centos7 常用的基本命令--目录管理、基本属性

一、目录管理 1、cd &#xff08;切换目录&#xff09; cd 路径 &#xff1a;切换路径命令&#xff0c;路径可以是绝对路径&#xff0c;也可以是相对路径 ./ : 当前目录 返回上级目录&#xff1a; cd … 返回用户目录&#xff1a; cd ~ 2、ls&#xff08;列出目录&#xff…

开源考试系统 - 本地代码调试运行

文章目录一、后端部署1. 图形化克隆项目2. 命令克隆项目3. 创建数据库&#xff0c;初始化数据库脚本4. IntelliJ IDEA打开项目5. 数据库连接和redis配置6. 启动redis和后端程序6. 浏览器访问二、前端部署2.1. 打开源码安装依赖2.2. 依次启动admin端和student端2.3. 浏览器访问补…

KDD 2019论文解读:异构信息网络上的对抗生成学习

前言 网络表示学习是一种在低维空间中表示网络数据的方法&#xff0c;在异构信息网络分析中得到了广泛的应用。现有的异构信息网络表示学习方法虽然在一定程度上实现了性能的提高&#xff0c;但仍然存在一些主要的不足。最重要的是&#xff0c;它们通常采用负抽样的方法从网络…

剖析疫情环境下的国内云市场:大势所趋,正是大展拳脚的好时机!

作者 | 马超责编 | Carol封图 | CSDN 付费下载于视觉中国4月29日&#xff0c;谷歌的母公司Alphabet正式发布了2020年第一季度财报&#xff0c;报告显示&#xff0c;Alphabet比去年同期的363.39亿美元增长13%&#xff0c;不计入汇率变动的影响为同比增长15%&#xff1b;在业绩公…

开源考试系统 -微信小程序开发

文章目录一、小程序前置准备1. 创建小程序2. 下载小程序开发工具二、小程序后端部署2.1. 配置修改2.2. 启动redis2.3. 启动后端项目三、小程序前端部署3.1. 微信小程序打开项目3.2. 学生端登录页面3.3. admin端登录一、小程序前置准备 1. 创建小程序 去腾讯小程序官网注册账号…

linux-centos7 常用的基本命令--文件内容查看、硬链接和软链接

一、文件内容查看 1、cat &#xff08;由第一行开始显示文件内容&#xff09; cat [-AbeEnstTuv] [--help] [--version] fileName参数说明&#xff1a; -n 或 --number&#xff1a;由 1 开始对所有输出的行数编号。-b 或 --number-nonblank&#xff1a;和 -n 相似&#xff0…

共享学习:蚂蚁金服数据孤岛解决方案

如果有A、B、C三位同学&#xff0c;他们各自手上有10、15、20块钱&#xff0c;这时需要在相互不知道对方有多少钱的情况下&#xff0c;不借助力第三方来计算三个人一共有多少钱。请问这时候&#xff0c;我们如何实现呢&#xff1f;——这&#xff0c;就是最经典的秘密共享场景。…

学之思开源考试系统 - 使用手册

文章目录一、前期准备1. 启动后端2. 启动前台管理员端3. 启动前台学员端二、用户添加2.1. 学生添加2.2. 管理员添加三、题目管理3.1. 添加学科2.2. 单选题添加2.3. 多选题添加2.4. 判断题添加2.5. 填空题添加2.6. 简答题添加四、试卷管理4.1. 固定试卷添加4.2. 时段试卷添加4.3…

看似简单的搜索引擎,原来背后的数据结构和算法这么复杂?

来源 | 码海封图 | CSDN 付费下载于视觉中国前言我们每天都在用 Google, 百度这些搜索引擎&#xff0c;那大家有没想过搜索引擎是如何实现的呢&#xff0c;看似简单的搜索其实技术细节非常复杂&#xff0c;说搜索引擎是 IT 皇冠上的明珠也不为过&#xff0c;今天我们来就来简单…

阿里巴巴在应用性能测试场景设计和实现上的实践

本文是《Performance Test Together》&#xff08;简称PTT&#xff09;系列专题分享的第5期&#xff0c;该专题将从性能压测的设计、实现、执行、监控、问题定位和分析、应用场景等多个纬度对性能压测的全过程进行拆解&#xff0c;以帮助大家构建完整的性能压测的理论体系&…

linux-centos7 常用的基本命令--Vim编辑器

一、Vim编辑器 1、什么是 vim&#xff1f; Vim通过一些插件可以实现和IDE一样的功能&#xff01; Vim 是从 vi 发展出来的一个文本编辑器。代码补全、编译及错误跳转等方便编程的功能特别丰富&#xff0c;在程序员中被广泛使用。 简单的来说&#xff0c; vi 是老式的字处理器…

linux-centos7 常用的基本命令--用户账号管理、查看和修改主机名

简介 Linux系统是一个多用户多任务的分时操作系统&#xff0c;任何一个要使用系统资源的用户&#xff0c;都必须首先向系统管理员申请一个账号&#xff0c;然后以这个账号的身份进入系统。 用户的账号一方面可以帮助系统管理员对使用系统的用户进行跟踪&#xff0c;并控制他们…

领导者必备:三元简化模型,助你加速团队成长

关注成员成长 很早之前&#xff0c;现代管理之父德鲁克提出过一个影响深远的观点&#xff0c;“21世纪的组织&#xff0c;最有价值的资产是组织内的知识工作者和他们的生产力。”现代企业的各位管理者&#xff0c;遇到最大的两类问题就是战略和组织&#xff0c;看不到、想不到…

90% 程序员都吃亏在这门技术上了,你呢!

老李一直怀疑自己是不是年纪大了&#xff0c;脑子跟不上了。作为十几年经验的资深 Java 工程师&#xff0c;维护这公司产品的核心代码的他&#xff0c;现在迭代产品的时候&#xff0c;经常出 Bug 。有时修复一个 Bug 时间&#xff0c;比开发一个需求的时间要长很多&#xff0c;…

车载多传感器融合定位方案:GPS +IMU+MM

导读 高德定位业务包括云上定位和端上定位两大模块。其中&#xff0c;云上定位主要解决Wifi指纹库、AGPS定位、轨迹挖掘和聚类等问题&#xff1b;端上定位解决手机端和车机端的实时定位问题。近年来&#xff0c;随着定位业务的发展&#xff0c;用户对在城市峡谷&#xff08;高…

linux-centos7 常用的基本命令--用户组管理

用户组管理 每个用户都有一个用户组&#xff0c;系统可以对一个用户组中的所有用户进行集中管理&#xff08;开发、测试、运维、root&#xff09;。不同Linux 系统对用户组的规定有所不同&#xff0c;如Linux下的用户属于与它同名的用户组&#xff0c;这个用户组在创建用户时同…

我画了35张图,就是为了让你深入 AQS!

来源 | 程序员cxuan责编 | Carol谈到并发&#xff0c;我们不得不说AQS(AbstractQueuedSynchronizer)&#xff0c;所谓的AQS即是抽象的队列式的同步器&#xff0c;内部定义了很多锁相关的方法&#xff0c;我们熟知的ReentrantLock、ReentrantReadWriteLock、CountDownLatch、Sem…

Cassandra Java堆外内存排查经历全记录

背景 最近准备上线cassandra这个产品&#xff0c;同事在做一些小规格ECS(8G)的压测。压测时候比较容易触发OOM Killer&#xff0c;把cassandra进程干掉。问题是8G这个规格我配置的heap(Xmx)并不高&#xff08;约6.5g&#xff09;已经留出了足够的空间给系统。只有可能是Java堆…

数据中台之结构化大数据存储设计

前言 任何应用系统都离不开对数据的处理&#xff0c;数据也是驱动业务创新以及向智能化发展最核心的东西。这也是为何目前大多数企业都在构建数据中台的原因&#xff0c;数据处理的技术已经是核心竞争力。在一个完备的技术架构中&#xff0c;通常也会由应用系统以及数据系统构…

清华硕士爆料:这些才是机器学习必备的数学基础

现如今&#xff0c;计算机科学、人工智能、数据科学已成为技术发展的主要推动力。无论是要翻阅这些领域的文章&#xff0c;还是要参与相关任务&#xff0c;你马上就会遇到一些拦路虎&#xff1a;想过滤垃圾邮件&#xff0c;不具备概率论中的贝叶斯思维恐怕不行&#xff1b;想试…