字符串操作 — Google Guava
前言
Java 里字符串表示字符的不可变序列,创建后就不能更改。在我们日常的工作中,字符串的使用非常频繁,熟练的对其操作可以极大的提升我们的工作效率,今天要介绍的主角是 Google 开源的一个核心 Java 库 Guava,它提供了集合类型、不可变的集合、并发、I / O、缓存、字符串等许多实用功能。在本文中,我们将学习使用 Guava 中的 Strings 和 Splitter 字符串操作工具类。
如何使用
Google Guava 会同步到 Maven Central 中,所以,如果你是 Maven 项目的话只需要在 pom.xml 文件中引入如下依赖即可:
<dependency>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
<version>28.2-jre</version>
</dependency>
对于 Gradle 项目在 build.gradle 中引入如下依赖即可:
compile group: 'com.google.guava', name: 'guava', version: '28.2-jre'
PS:28.2-jre 是编写本文时的最新版本,你可以从 Maven Central 中查看当前的最新版本。
为什么需要引入类库
Google Guava 提供了很多实用的静态方法,这些可以解决开发人员在开发中所要完成的一些重复任务。当然,这个工作我们也可以自己做,但是引入类库它会降低错误发生的可能性,毕竟这些类库都是已经经过多年的生产验证。比如类库中 Strings 提供的一个方法 commonPrefix,它接受两个字符串并返回两个字符串之间的公共前缀(eg: abcd 和 abef 返回 ab)。你可以在脑子里想象一下在应用程序代码中面临这样的要求时,自己要如何编写代码来完成该操作,要自己实现这个功能,还是需要花费一些时间的,同时还需要考虑到各种边界异常情况。这就是类库提供给我们的最大价值之一,所以当我们需要的某种功能可以作为一种工具方法使用时,首先应该去寻找一些已存在的类库并去熟练使用的它们,而不是自己去实现。总结起来使用类库有如下几个原因:
Google Guava类库有人已经对其进行了彻底的测试,bug出现的概率会比我们自己实现的小很多- 作为
Google Guava的一部分,已经存在各种测试用例,用于测试实用程序的实现。如果我们自己编写代码实现的话,可能还要去编写和维护它们的测试。
Strings
Google Guava 有许多实用的工具类和方法,不可能在一篇文章中都有介绍完,在本文中,只会介绍和字符串操作相关的两个工具类。首先第一个是 Strings 类,该类提供了操作 String 和 CharSequence 的实用方法。
nullToEmpty、emptyToNull 和 isNullOrEmpty
nullToEmpty 方法功能为:如果传入的字符串为 null,则返回一个空字符串 "",否则,返回一个空字符串,否则按原样返回传递的字符串。
@Test
public void testStringsOfNullToEmpty() {
System.out.println(Strings.nullToEmpty("mghio")); // mghio
System.out.println(Strings.nullToEmpty("")); // ""
System.out.println(Strings.nullToEmpty(null)); // ""
System.out.println(Strings.nullToEmpty(null).isEmpty()); // true
}
emptyToNull 方法功能为:它与 nullToEmpty 相反,如果传入了空字符串,则返回 null,否则返回原始字符串。
@Test
public void testStringsOfEmptyToNull() {
System.out.println(Strings.emptyToNull("mghio")); // mghio
System.out.println(Strings.emptyToNull(null)); // null
System.out.println(Strings.emptyToNull("")); // null
}
isNullOrEmpty 方法功能为:如果传入的字符串为 null 或为空,则返回 true,否则返回 false。
@Test
public void testStringsOfIsNullOrEmpty() {
System.out.println(Strings.isNullOrEmpty("mghio")); // false
System.out.println(Strings.isNullOrEmpty("")); // true
System.out.println(Strings.isNullOrEmpty(null)); // true
}
padStart 和 padEnd
这两个方法有三个参数,分别为:输入字符串、最小长度和要填充的字符,它将字符根据需要多次插入到输入字符串的开头,以使输入字符串的长度等于传入的最小长度。
@Test
public void testStringsOfPadStart() {
System.out.println(Strings.padStart("9527", 6, '0')); // 009527
System.out.println(Strings.padStart("123456", 6, '0')); // 123456
}
在第一行代码中,将两次填充 0 以使最终的字符串长度等于我们传入的最小长度(6)。在第二行代码中,输入字符串长度本身具有所需的最小长度,因此未进行填充padEnd 方法和上面这个方法类似,只不过它是在字符的末尾而不是在开始处进行填充。
@Test
public void testStringsOfPadEnd() {
System.out.println(Strings.padEnd("9527", 6, '0')); // 952700
System.out.println(Strings.padEnd("123456", 6, '0')); // 123456
}
repeat
该方法需要传入一个字符串和一个重复次数 count,它返回一个由原始字符串组成的字符串,该字符串重复了 count 次。
@Test
public void testStringsRepeat() {
System.out.println(Strings.repeat("mghio", 3)); // mghiomghiomghio
}
commonPrefix 和 commonSuffix
commonPrefix 方法返回传入的两个字符串之间最大的公共前缀,而 commonSuffix 方法返回传入两个字符串之间最大的公共后缀。
@Test
public void testStrings() {
System.out.println(Strings.commonPrefix("mghio9527", "mghio666")); // mghio
System.out.println(Strings.commonSuffix("iammghio", "nicemghio")); // mghio
}
Splitter
Splitter 类提供的功能正如其名(PS:一个好的命名很重要),它用于根据提供的分割符将字符串拆分为多个子字符串。我们可以通过传入一个分割符来获一个 Splitter 的实例,有了分割器之后,我们可以根据分割器的配置方式对字符串进行分割。
@Test
public void testSplitterOfSplit() {
Iterable<String> result = Splitter.on(",").split("m,g,h,i,o");
System.out.println(result); // [m, g, h, i, o]
}
上面的例子中使用逗号进行分割,因此,它将传入的字符串 m,g,h,i,o 拆分为一个 Iterable <String>,然后当我们对其进行迭代遍历时会输出 [m, g, h, i, o]。
获取 Splitter 实例
on 和 onPattern
现在,我们来看看获得一个分割器 Splitter 的各种方法。on 方法有各种不同的重载版本,它们以字符、字符串或正则表达式作为分隔符,我们还可以将 Pattern 实例作为字符串传递给 onPattern 方法中。
@Test
public void testSplitterOfOn() {
Splitter wordSplitter = Splitter.on(":;");
// 下面这行输出结果 [the, text, is, separated, by, colon, semicolon]
System.out.println(wordSplitter.split("the:;text:;is:;separated:;by:;colon:;semicolon"));
Splitter patternBasedSplitter = Splitter.on(Pattern.compile("\\s+"));
System.out.println(patternBasedSplitter.split("abc dmg hio")); // [abc, dmg, hio]
System.out.println(Splitter.onPattern("\\s+").split("www mghio cn")); // [www, mghio, cn]
}
fixedLength
fixedLength 也是最有用的方法之一,它可以将字符串分成给定长度的相等部分,需要注意的是,最后一个部分可能会小于给定的长度。
@Test
public void testSplitterOfFixedLength() {
Splitter fixedLengthSplitter = Splitter.fixedLength(3);
System.out.println(fixedLengthSplitter.split("iammghiojava")); // [iam, mgh, ioj, ava]
System.out.println(fixedLengthSplitter.split("https://www.mghio.cn")); // [htt, ps:, //w, ww., mgh, io., cn]
}
Splitter 修饰符方法
Splitter 还提供了可以在更改或修改 Splitter 行为的常用方法。
trimResults
这个方法可以从生成的分割器的结果字符串中删除前面和末尾的空格。
@Test
public void testSplitterOfTrimResult() {
Splitter commaSplitter = Splitter.on(",");
System.out.println(commaSplitter.split("m, g, h, i, o")); // [m, g, h, i, o]
Splitter commaSplitterWithTrim = commaSplitter.trimResults();
System.out.println(commaSplitterWithTrim.split("m, g, h, i, o")); // [m, g, h, i, o]
}
注意,第一个分割的结果在字符串 g、 h、i、o 之前有一个空格,使用 trimResults 方法后,将去除这些前导空格。
omitEmptyStrings
这个方法会从结果中忽略所有空字符串。
@Test
public void testSplitterOfOmitEmptyStrings() {
Splitter commaSplitter = Splitter.on(",");
System.out.println(commaSplitter.split("m,,g,h,i,o")); // [m, , g, h, i, o]
Splitter commaSplitterWithNoEmptyString = commaSplitter.omitEmptyStrings();
System.out.println(commaSplitterWithNoEmptyString.split("m,,g,h,i,o")); // [m, g, h, i, o]
}
上面的 commaSplitterWithNoEmptyString 会从输出中删除空字符串的结果。
limit
这个方法返回与原始分割器等效的分割器,但它会在达到指定的输入限制后将停止拆分,将后续剩余结果字符串作为一项输出,也就是说,我们可以通过的传入的参数指定结果中存在的最大项目数。需要注意的是:该方法在省略空字符串时,省略的字符串不计算在内。。
@Test
public void testSplitterOfLimit() {
Splitter commaSplitter = Splitter.on(",");
Splitter limitingCommaSplitter = commaSplitter.limit(3);
System.out.println(limitingCommaSplitter.split("i,m,g,h,i,o")); // [i, m, g,h,i,o]
}
有一点需要注意,Splitter 是不可变的(这一点和 String 类似),因此,调用它的任何修饰符方法都将返回新的 Splitter,并且不会修改原始的 Splitter。
@Test
public void testSplitterImmutable() {
Splitter splitter = Splitter.on('/');
System.out.println("Before: " + splitter); // Before: com.google.common.base.Splitter@33b37288
splitter.trimResults(); // do nothing
System.out.println("First: " + splitter); // First: com.google.common.base.Splitter@33b37288
splitter = splitter.trimResults(); // the returned splitter to be assigned
System.out.println("Second: " + splitter); // Second: com.google.common.base.Splitter@77a57272
}
splitToList
我们前面已经使用的 split 方法,它返回的是一个 Iterable<String> 对象。而这里的 splitToList 方法返回一个 List<String>。由于分割方法返回的是 Iterable,因此它是惰性的。
@Test
public void testSplitterOfSplitToList() {
Splitter commaSplitter = Splitter.on(",");
List<String> result = commaSplitter.splitToList("m,g,h,i,o");
System.out.println(result); // [m, g, h, i, o]
}
MapSplitter
MapSplitter 顾名思义就是用来将一个将字符串拆分为 Map 对象的。我们可以使用 withKeyValueSeparator 方法从 Splitter 中获取 MapSplitter 对象,该方法接收一个字符、字符串或者 Splitter 对象作为参数。首先,根据原始的分割器将字符串分割为多个项,然后,使用传给 withKeyValueSeparator 方法的分割符将各个项分为 Map 键-值对。
@Test
public void testSplitterOfWithKeyValueSeparator() {
Splitter commaSplitter = Splitter.on(',');
Splitter.MapSplitter keyValueSplitter = commaSplitter.withKeyValueSeparator('=');
Map<String, String> map = keyValueSplitter.split("name=mghio,blog=mghio.cn");
System.out.println(map); // {name=mghio, blog=mghio.cn}
}
从结果可以看到,它分割为两个 entry (name=mghio 与 blog=mghio.cn)项,还有一个点需要注意的是:如果我们在原始的分割器上指定了任何修改器,则它们仅适用于该分割器,而不适用于 MapSplitter。
@Test
public void testSplitterOfWithKeyValueSeparatorAndModifiers() {
Splitter originalSplitter = Splitter.on(",").trimResults();
Splitter.MapSplitter keyValueSplitter = originalSplitter.withKeyValueSeparator('=');
// 输出结果:{name =mghio, blog= mghio.cn}
System.out.println(keyValueSplitter.split("name =mghio, blog= mghio.cn"));
}
由以上结果可以看出 trimResults 修饰方法仅适用于原始拆分器。因此,blog 开头的空格已被移除(使用 , 分割原始字符串时),但是,mghio.cn 开头的空格不会被移除(使用 = 分割成键值时)。
最后需要注意的是:MapSplitter 类被标记为 @Beta,这意味着类库中与 MapSplitter 相关的类和方法是实验性的,可以更改(以中断的方式),甚至将来版本可能删除。
总结
在本文中,介绍了 Google Guava 库以及在项目或应用程序中使用它的好处,如何将其导入到我们的应用程序中使用。然后,介绍了 Guava 库中对字符串操作工具类(Strings 和 Splitter )的一些基本用法,当然,这只是冰山一角,Guava 库还提供了其它很多有用的基础功能,需要我们自己去查询相关文档学习了解,感兴趣的朋友可以去看看它的实现源码,这个库的代码写得很优雅。
参考
字符串操作 — Google Guava的更多相关文章
- Google Guava官方教程(中文版)
Google Guava官方教程(中文版) 原文链接 译文链接 译者: 沈义扬,罗立树,何一昕,武祖 校对:方腾飞 引言 Guava工程包含了若干被Google的 Java项目广泛依赖 的核心库, ...
- 使用 Google Guava 美化你的 Java 代码
文章转载自:http://my.oschina.net/leejun2005/blog/172328 目录:[ - ] 1-使用 GOOGLE COLLECTIONS,GUAVA,STATIC IMP ...
- Google Guava之--cache
一.简介 Google Guava包含了Google的Java项目许多依赖的库,如:集合 [collections] .缓存 [caching] .原生类型支持 [primitives support ...
- Google Guava学习笔记——简介
Google Guava是什么东西?首先要追溯到2007年的“Google Collections Library”项目,它提供对Java 集合操作的工具类.后来Guava被进化为Java程序员开发必 ...
- Google Guava的5个鲜为人知的特性
译文出处: 花名有孚 原文出处:takipi.com Google Guava有哪些比较冷门但却又实用的特性呢? 它是最流行的开源库之一,你应该听过它的大名,它诞生的地方正是人们举办真正的魁地奇比 ...
- 初探Google Guava
Guava地址:https://github.com/google/guava 第一次接触我是在16年春github上,当时在找单机查缓存方法,google guava当初取名是因为JAVA的类库不好 ...
- Google Guava新手教程
以下资料整理自网络 一.Google Guava入门介绍 引言 Guavaproject包括了若干被Google的 Java项目广泛依赖 的核心库,比如:集合 [collections] . ...
- Google Guava 类库简介
Guava 是一个 Google开发的 基于java的类库集合的扩展项目,包括 collections, caching, primitives support, concurrency librar ...
- Google guava工具类的介绍和使用
概述 工具类 就是封装平常用的方法,不需要你重复造轮子,节省开发人员时间,提高工作效率.谷歌作为大公司,当然会从日常的工作中提取中很多高效率的方法出来.所以就诞生了guava.. 高效设计良好的API ...
随机推荐
- plist 图集 php 批量提取 PS 一个个切
最近,迷上了用 cocos2d 做游戏开发.由于是新入门,很多东西从头开始学. 在使用 sprite 的 Rect 裁剪显示的时候,显示总是多一块.所以,要从图集中提取一张张图,这样就省了裁剪. 原图 ...
- cocos2d-x android 入门
前一段时间使用传统方式做了一个CS软件,发现 UI 显示的比较慢,突发奇起,开始研究起来 GPU 加速,最后开始学习 cocos2dx. 开发环境以最新的 Cocos2d-x 3.17.1 Andro ...
- mongo复制数据库和表
1.使用工具Studio 3T for MongoDB 选择一个数据库中的Collections集合,然后按住 Ctrl+C 复制快捷键会弹出如下帮助框. 点击 Ctrl+V 粘贴快捷键,重命名一下复 ...
- ASP.net MVC 构建layui管理后台(构造基础仓储)<1>
本文章为ASP.net MVC 构建layui管理后台,第一篇. 使用EF+ado.net 实体数据模型模式进行底层的数据库连接. 在项目添加一个类库Model 在类库Model上添加一个ado.ne ...
- go例子(三) 使用context实现发牌手策略
使用context包实现发牌手策略, 发牌手策略:罗永浩在介绍TNT工作站时描述,将一个任务分发给多个处理者处理,谁先处理完使用谁的结果,取消其他的处理者的任务. 经典的例子:同时在百度.google ...
- vue中的$props、$attrs和$listeners研究 [包装iview组件]
$props:当前组件接收到的 props 对象.Vue 实例代理了对其 props 对象属性的访问. $attrs:包含了父作用域中不作为 prop 被识别 (且获取) 的特性绑定 (class 和 ...
- 最全ElasticSearch6.5白金版本从构建ELK、集群搭建到和Mybatis结合操作详细讲解
1.安装ElasticSearch6.5.1 解压相关的ElasticSearch6.5.1的tar包到目录下,如果我们需要使用JDBC来连接的话是需要到白金版以上的,以下为将基础版破解为白金版的方法 ...
- Mol Cell Proteomics. | 用于鉴定新型融合转录本及其在癌细胞中的潜在翻译产物的多功能蛋白质组基因组学工具FusionPro
期刊:Molecular & Cellular Proteomics 发表时间:June 17, 2019 DOI:10.1074/mcp.RA119.001456 分享人:任哲 内容与观点: ...
- 一款带Web面板的轻量级、高性能内网穿透工具:nps使用教程
说明:内网穿透工具之前已经介绍了不少了,比如Frp.lanproxy.Holer等,现在再介绍个带Web面板的穿透工具nps,之前叫easyProxy,只是改名了而已,该工具是一款使用go语言编写的轻 ...
- CF1324F Maximum White Subtree 题解
原题链接 简要题意: 给定一棵树,每个点有黑白两种颜色:对每个节点,求出包含当前节点的连通图,使得白点数与黑点数差最小.输出这些值. F题也这么简单,咳咳,要是我也熬夜打上那么一场...可惜没时间打啊 ...