Google Guava之字符串处理

Google Guava之字符串处理

Google Guava依赖

<!-- https://mvnrepository.com/artifact/com.google.guava/guava -->
<dependency>
    <groupId>com.google.guava</groupId>
    <artifactId>guava</artifactId>
    <version>30.1.1-jre</version>
</dependency>

连接器[Joiner]

连接器工厂

方法描述范例
Joiner.on(char)按单个字符连接Joiner.on(’,’)
Joiner.on(CharMatcher)按字符匹配器连接Joiner.on(",")

连接器修饰符

方法描述
skipNulls()过滤字符串序列中的null值
useForNull(String)替换字符串序列中的null值
join(Iterable)连接对象类型的数据

用分隔符把字符串序列连接起来也可能会遇上不必要的麻烦。如果字符串序列中含有null,那连接操作会更难。Fluent风格的Joiner符串更简单。

String joinerStr = Joiner.on(";").skipNulls().join("Harry", null, "Ron", "Hermione");
//Harry;Ron;Hermione

另外,useForNull(String)方法可以给定某个字符串来替换null,而不像skipNulls()方法是直接忽略nullJoiner也可以用来连接对象类型,在这种情况下,它会把对象的toString()值连接起来。

String joinerStr = Joiner.on(";").useForNull("aries").join("Harry", null, "Ron", "Hermione");
//Harry;aries;Ron;Hermione
//User中包含age和name两个属性
User user1 = User.builder().age(18).name("张三").build();
User user2 = User.builder().age(19).name("李四").build();
String join = Joiner.on(";").join(Arrays.asList(user1, user2));
//User(age=18, name=张三);User(age=19, name=李四)

警告:joiner实例总是不可变的。用来定义joiner目标语义的配置方法总会返回一个新的joiner实例。这使得joiner实例都是线程安全的,你可以将其定义为static final常量。

拆分器[Splitter]

JDK内建的字符串拆分工具有一些古怪的特性。比如,Stringsplit()方法悄悄丢弃了尾部的分隔符。

Splitter使用令人放心的、直白的流式API模式对这些混乱的特性做了完全的掌控。

拆分器工厂

方法描述范例
Splitter.on(char)按单个字符拆分Splitter.on(‘;’)
Splitter.on(CharMatcher)按字符匹配器拆分Splitter.on(CharMatcher.breakingWhitespace())
Splitter.on(String)按字符串拆分Splitter.on(“, “)
Splitter.on(Pattern) Splitter.onPattern(String)按正则表达式拆分Splitter.onPattern(“\r\n”)
Splitter.fixedLength(int)按固定长度拆分;最后一段可能比给定长度短,但不会为空Splitter.fixedLength(3)

拆分器修饰符

方法描述
omitEmptyStrings()从结果中自动忽略空字符串
trimResults()移除结果字符串的前导空白和尾部空白
trimResults(CharMatcher)给定匹配器,移除结果字符串的前导匹配字符和尾部匹配字符
limit(int)限制拆分出的字符串数量
split(final CharSequence)拆分结果为Iterable
splitToList(CharSequence)拆分结果为List
List<String> splitList = Splitter.on(',')
                .trimResults()
                .omitEmptyStrings()
                .splitToList("apple,watermelon,,    banana");
//[apple, watermelon, banana]

注:splitter实例总是不可变的。用来定义splitter目标语义的配置方法总会返回一个新的splitter实例,这使得splitter实例都是线程安全的,你可以将其定义为static final常量。

字符匹配器[CharMatcher]

在以前的Guava版本中,StringUtil类疯狂地膨胀,其拥有很多处理字符串的方法:allAscii、collapse、collapseControlChars、collapseWhitespace、indexOfChars、lastIndexNotOf、numSharedChars、removeChars、removeCrLf、replaceChars、retainAllChars、strip、stripAndCollapse、stripNonDigits。 所有这些方法指向两个概念上的问题:

  1. 怎么才算匹配字符?
  2. 如何处理这些匹配字符?

为了收拾这个泥潭,我们开发了CharMatcher。

直观上,你可以认为一个CharMatcher实例代表着某一类字符,如数字或空白字符。事实上来说,CharMatcher实例就是对字符的布尔判断—CharMatcher确实也实现了Predicate—但类似”所有空白字符”或”所有小写字母”的需求太普遍了,Guava因此创建了这一API。

然而使用CharMatcher的好处更在于它提供了一系列方法,让你对字符作特定类型的操作:修剪[trim]、折叠[collapse]、移除[remove]、保留[retain]等等。这样的设计使得API复杂度的线性增加可以带来灵活性和功能两方面的增长。

获取字符匹配器

获取字符匹配器的常见方法包括:

方法描述
any()匹配任何字符
none()不匹配所有字符
whitespace()匹配所有空白字符
breakingWhitespace()匹配所有可换行的空白字符(不包括非换行空白字符,例如"\u00a0")
invisible()匹配所有看不见的字符
digit()匹配ASCII数字
javaLetter()匹配字母
javaDigit()匹配UNICODE数字
javaLetterOrDigit()匹配数字或字母
javaIsoControl()匹配ISO控制字符(制表符、回车、换行等)
javaLowerCase()匹配小写
javaUpperCase()匹配大写
ascii()匹配ASCII字符
singleWidth()匹配单字宽字符, 如中文字就是双字宽
anyOf(CharSequence)枚举匹配字符。如CharMatcher.anyOf(“aeiou”)匹配小写英语元音
is(char)给定单一字符匹配
inRange(char, char)给定字符范围匹配,如CharMatcher.inRange(‘a’,‘z’)
negate()返回以当前Matcher判断规则相反的Matcher
and(CharMatcher)返回与其他匹配条件组合来做与判断的Matcher
or(CharMatcher)返回与其他匹配条件组合来做或判断的Matcher

使用字符匹配器

CharMatcher提供了多种多样的方法操作CharSequence中的特定字符。其中最常用的罗列如下:

方法描述
collapseFrom(CharSequence,char)把每组连续的匹配字符替换为特定字符。如whitespace().collapseFrom(str,';')把字符串中的连续空白字符替换为";"
matchesAllOf(CharSequence)测试是否字符序列中的所有字符都匹配
removeFrom(CharSequence)从字符序列中移除所有匹配字符
retainFrom(CharSequence)在字符序列中保留匹配字符,移除其他字符
trimFrom(CharSequence)移除字符序列的前导匹配字符和尾部匹配字符
replaceFrom(CharSequence,CharSequence)用特定字符序列替代匹配字符
trimAndCollapseFrom(CharSequence,char)去除两端的空格,并把中间连续的匹配字符替换为特定字符

所有这些方法返回String,除了matchesAllOf()返回的是boolean

String str = "abc\td123  ABC";

//移除control字符
String noControl = CharMatcher.javaIsoControl().removeFrom(str); 
//abcd123  ABC

//只保留数字字符
String theDigits = CharMatcher.digit().retainFrom(str);
//123

//去除两端的空格,并把中间的连续空格替换成";"(\t也会被当做空格)
String spaced = CharMatcher.whitespace().trimAndCollapseFrom(str, ';');
//abc;d123;ABC

//用*号替换所有数字
String noDigits = CharMatcher.javaDigit().replaceFrom(str, "*");
//abc	d***  ABC

// 只保留数字和小写字母
String lowerAndDigit = CharMatcher.javaDigit().or(CharMatcher.javaLowerCase()).retainFrom(str);
//abcd123

注:CharMatcher只处理char类型代表的字符;它不能理解0x10000到0x10FFFF的Unicode 增补字符。这些逻辑字符以代理对[surrogate pairs]的形式编码字符串,而CharMatcher只能将这种逻辑字符看待成两个独立的字符。

字符集[Charsets]

不要这样做字符集处理:

String str = "abc";
try {
    byte[] bytes = str.getBytes("UTF-8");
} catch (UnsupportedEncodingException e) {
    throw new AssertionError(e);
}

试试这样写:

byte[] bytes = string.getBytes(Charsets.UTF_8);

Charsets针对所有Java平台都要保证支持的六种字符集提供了常量引用。尝试使用这些常量,而不是通过名称获取字符集实例。

大小写格式[CaseFormat]

CaseFormat被用来方便地在各种ASCII大小写规范间转换字符串—比如,编程语言的命名规范。CaseFormat支持的格式如下:

格式描述范例
LOWER_CAMELJava变量的命名规则,如“lowerCamel”lowerCamel
LOWER_HYPHEN连字符连接变量的命名规则,如“lower-hyphen”lower-hyphen
LOWER_UNDERSCOREC ++变量命名规则,如“lower_underscore”lower_underscore
UPPER_CAMELJava和C++类的命名规则,如“UpperCamel”UpperCamel
UPPER_UNDERSCOREJava和C++常量的命名规则,如“UPPER_UNDERSCORE”UPPER_UNDERSCORE

CaseFormat的用法很直接:

String to(CaseFormat format, String str):从这一格式指定格式的指定字符串str转换

//常量命名规则转换小驼峰命名规则
CaseFormat.UPPER_UNDERSCORE.to(CaseFormat.LOWER_CAMEL, "CONSTANT_NAME");
//constantName

我们CaseFormat在某些时候尤其有用,比如编写代码生成器的时候。
在这里插入图片描述

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

第二范式

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值