拥抱Guava之字符串操作

Guava字符串操作

在Java开发的道路上,我们经常会面临各种各样的字符串处理任务,从简单的判空到复杂的拆分和连接操作。为了简化这些常见但有时繁琐的任务,Google推出了一款强大的Java库——Guava。Guava不仅为我们提供了丰富的集合工具,还包括了许多方便而高效的字符串处理工具。

在本文中,我们将专注于探讨Guava库中关于字符串操作的强大功能。无论您是正在寻找更好的字符串拆分方法,还是希望提高代码的可读性和性能,Guava都为您提供了解决方案。

一、连接器【Joiner】

Joiner是字符串连接器,可以处理字符串中的null值,简洁方便。

1、常用方法:
方法名称 描述 范例
skipNulls() 跳过空值
useForNull(String) 使用参数替换字符串中的null值
withKeyValueSeparator(String) 使用参数连接map结构
2、Joiner的使用分为三个步骤:

(1)、on方法用来设置链接符

(2)、在on方法之后 join方法之前 ,我们可以做一些扩展操作,比如s使用useForNull是为null值设置默认值。

(3)、join方法用来设置被操作的集合

3、使用示例:
@Test
public void joinerTest(){
    List<String> list = Lists.newArrayList("Hello",null,"World","!");

    // skipNulls
    Joiner joiner = Joiner.on(" ").skipNulls();
    System.out.println(joiner.join(list));

    // useForNull
    joiner = Joiner.on(" ").useForNull("My");
    System.out.println(joiner.join(list));

    // withKeyValueSeparator
    Map<String, String> map = ImmutableMap.of("a","1","b","2");
    System.out.println(Joiner.on(";").withKeyValueSeparator("-").join(map));
}

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

二、字符串拆分器【Splitter】

Splitter可以被设置为按照任何模式、字符、字符串或字符匹配器拆分。返回一个Iterable

1、拆分器工厂
方法 描述 范例
Splitter.on(Char) 按照单个字符拆分 Splitter.on(“,”)
Splitter.on(CharMatcher) 按字符匹配器拆分 Splitter.on(CharMatcher.BREAKING_WHITESPACE)
Splitter.on(String) 按字符串拆分 Splitter.on(“a”)
Splitter.on(Pattern)
Splitter.onPattern(String)
按正则表达式拆分 Splitter.onPattern(“\r?\n”)
Splitter.fixedLength(int) 按固定长度拆分;最后一段可能比给定长度短,但不会为空。 Splitter.fixedLength(3)
2、拆分器修饰符
方法 描述
omitEmptyStrings() 从结果中自动忽略空字符串
trimResults() 移除结果字符串的前导空白和尾部空白
trimResults(CharMatcher) 给定匹配器,移除结果字符串的前导匹配字符和尾部匹配字符
limit(int) 限制拆分出的字符串数量,即只有前几个拆分符生效
splitToList 将拆分接口用List返回
withKeyValueSeparator 将String转换Map
3、示例
 @Test
 public void splitterTest(){
     // trimResults 去掉头尾空格 |a||b|c||
     List<String> splitterList = Splitter.on(",").trimResults().splitToList(" ,a,,b,c,, ");
     System.out.println(Joiner.on("|").join(splitterList));

     // omitEmptyStrings 忽略空串  |a|b|c|
     splitterList = Splitter.on(",").omitEmptyStrings().splitToList(" ,a,,b,c,, ");
     System.out.println(Joiner.on("|").join(splitterList));

     // 两者一起使用 a|b|c
     splitterList = Splitter.on(",").trimResults().omitEmptyStrings().splitToList(" ,a,,b,c,, ");
     System.out.println(Joiner.on("|").join(splitterList));

     // limit a|b,c,,
     splitterList = Splitter.on(",").trimResults().omitEmptyStrings().limit(2).splitToList(" ,a,,b,c,, ");
     System.out.println(Joiner.on("|").join(splitterList));

     // withKeyValueSeparator  a=1|b=2
     Map<String, String> splitterMap = Splitter.on(";").withKeyValueSeparator("-").split("a-1;b-2");
     System.out.println(Joiner.on("|").withKeyValueSeparator("=").join(splitterMap));
 }

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

三、字符匹配器【CharMatcher】

直观上可以认为CharMatcher实例代表着某一类字符,如数字或空白字符。事实上来说,CharMatcher实例就是对字符的布尔判断——CharMatcher确实也实现了Predicate

使用CharMatcher的好处更在于它提供了一系列方法,让你对字符作特定类型的操作:修剪[trim]、折叠[collapse]、移除[remove]、保留[retain]等等。CharMatcher实例首先代表概念1:怎么才算匹配字符?然后它还提供了很多操作概念2:如何处理这些匹配字符?

1、常见字符匹配器常量
常量 描述
ANY 匹配任何字符
ASCII 匹配是否是ASCII字符
BREAKING_WHITESPACE 匹配所有可换行的空白字符(不包括非换行空白字符,例如"\u00a0")
DIGIT 匹配ASCII数字
INVISIBLE 匹配所有看不见的字符
JAVA_DIGIT 匹配UNICODE数字, 使用 Character.isDigit() 实现
JAVA_ISO_CONTROL 匹配ISO控制字符, 使用 Charater.isISOControl() 实现
JAVA_LETTER 匹配字母, 使用 Charater.isLetter() 实现
JAVA_LETTER_OR_DIGET 匹配数字或字母
JAVA_LOWER_CASE 匹配小写
JAVA_UPPER_CASE 匹配大写
NONE 不匹配所有字符
SINGLE_WIDTH 匹配单字宽字符, 如中文字就是双字宽
WHITESPACE 匹配所有空白字符
2、常用操作方法
CharMatcher is(char match): //返回匹配指定字符的Matcher 
CharMatcher isNot(char match): //返回不匹配指定字符的Matcher 
CharMatcher anyOf(CharSequence sequence): //返回匹配sequence中任意字符的Matcher CharMatcher noneOf(CharSequence sequence): //返回不匹配sequence中任何一个字符的Matcher **CharMatcher inRange(char startInclusive, char endInclusive): //返回匹配范围内任意字符的Matcher CharMatcher forPredicate(Predicate\<? super Charater> predicate): //返回使用predicate的apply()判断匹配的Matcher CharMatcher negate(): //返回以当前Matcher判断规则相反的Matcher
**CharMatcher and(CharMatcher other): //返回与other匹配条件组合做与来判断的Matcher **CharMatcher or(CharMatcher other): //返回与other匹配条件组合做或来判断的Matcher boolean matchesAnyOf(CharSequence sequence): //只要sequence中有任意字符能匹配Matcher,返回true boolean matchesAllOf(CharSequence sequence): //sequence中所有字符都能匹配Matcher,返回true boolean matchesNoneOf(CharSequence sequence): //sequence中所有字符都不能匹配Matcher,返回true int indexIn(CharSequence sequence): //返回sequence中匹配到的第一个字符的坐标 int indexIn(CharSequence sequence, int start): //返回从start开始,在sequence中匹配到的第一个字符的坐标 int lastIndexIn(CharSequence sequence): //返回sequence中最后一次匹配到的字符的坐标 int countIn(CharSequence sequence): //返回sequence中匹配到的字符计数 **String removeFrom(CharSequence sequence): //删除sequence中匹配到到的字符并返回 **String retainFrom(CharSequence sequence): //保留sequence中匹配到的字符并返回 **String replaceFrom(CharSequence sequence, char replacement): //替换sequence中匹配到的字符并返回 **String trimFrom(CharSequence sequence): //删除首尾匹配到的字符并返回 **String trimLeadingFrom(CharSequence sequence): //删除首部匹配到的字符 **String trimTrailingFrom(CharSequence sequence): //删除尾部匹配到的字符 **String collapseFrom(CharSequence sequence, char replacement): //将匹配到的组(连续匹配的字符)替换成replacement **String trimAndCollapseFrom(CharSequence sequence, char replacement): //先trim在replace>
3、示例:
@Test
public void charMatcherTest(){
 String testStr = "FirstName LastName +1 123 456 789 !@#$%^&*()_+|}{:\"?><";
 System.out.println(CharMatcher.digit().retainFrom(testStr));// 1123456789
 System.out.println(CharMatcher.javaLetter().retainFrom(testStr));// FirstNameLastName
 System.out.println(CharMatcher.javaLetterOrDigit().retainFrom(testStr)); // FirstNameLastName1123456789
 System.out.println(CharMatcher.javaLowerCase().retainFrom(testStr)); // irstameastame

 System.out.println(CharMatcher.any().countIn(testStr));// 54

 System.out.println(CharMatcher.inRange('0','9').retainFrom(testStr));// 1123456789
 System.out.println(CharMatcher.inRange('0','9').removeFrom(testStr));// FirstName LastName +    !@#$%^&*()_+|}{:"?><
 System.out.println(CharMatcher.inRange('0','9').or(CharMatcher.whitespace()).retainFrom(testStr)); //   1 123 456 789

 System.out.println(CharMatcher.inRange('0','9').or(CharMatcher.anyOf("abcd")).retainFrom(testStr));// aaa1123456789

 System.out.println(CharMatcher.inRange('0','9').replaceFrom(testStr,"*"));// FirstName LastName +* *** *** *** !@#$%^&*()_+|}{:"?><
}

注:CharMatcher只处理char类型代表的字符;

四、字符集【Charsets】

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

示例

bytes = string.getBytes(Charsets.UTF_8);

五、大小写格式【CaseFormat】

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

格式 范例
LOWER_CAMEL lowerCamel
LOWER_HYPHEN lower-hyphen
LOWER_UNDERSCORE lower_underscore
UPPER_CAMEL UpperCamel
UPPER_UNDERSCORE UPPER_UNDERSCORE
示例:
@Test
public void caseFormatTest(){
    System.out.println(CaseFormat.UPPER_UNDERSCORE.to(CaseFormat.LOWER_CAMEL,"FIRSTNAME"));// firstname
}

总结

在使用Guava字符串处理工具时,性能是一个不可忽视的因素。Guava库经过精心设计,旨在提供高效的操作,但在一些特定场景下,合理的性能考虑仍然是必要的。

首先,Guava的字符串处理工具通常在处理大规模数据时表现出色。例如,在使用Splitter进行字符串拆分时,Guava能够更有效地处理大型字符串,相较于传统的字符串拆分方法,这将在处理大量文本数据时体现出明显的性能优势。

其次,Guava的一些设计目标是为了避免不必要的内存分配和拷贝,从而提高性能。例如,使用Joiner连接字符串时,Guava可以更智能地处理拼接过程,减少临时对象的创建,从而降低了内存开销。然而,在某些场景下,如果性能是关键问题,开发者仍需谨慎选择适当的方法和工具。Guava提供了丰富的选项,通过合理地选择工具和参数,可以使得性能得到最优化。

Guava字符串处理工具为Java开发者提供了强大而灵活的解决方案,能够简化日常的字符串操作,并在性能方面展现出色的表现。通过本文的介绍,我们深入了解了Guava中关于字符串的各种特性,从基础的判空和拆分,到高级的不可变字符串。

在使用Guava时,我们学习了如何利用SplitterJoiner等工具执行各种字符串操作,以及如何通过CharMatcher处理字符匹配和替换。同时,我们也了解了不可变字符串的优势,以及在一些特定场景中的应用。

在选择使用Guava字符串处理工具时,我们需要根据具体的需求和场景来权衡灵活性和性能。Guava为我们提供了丰富的选择,让我们在处理字符串时更加便捷高效。

总的来说,Guava的字符串处理工具不仅为我们提供了更好的开发体验,同时也通过其高效的设计为项目性能提供了可靠的支持。在今后的Java开发中,深入了解并灵活应用Guava的字符串处理工具,将是提高代码质量和开发效率的不错选择。

本文已收录于我的个人博客:码农Academy的博客,专注分享Java技术干货,包括Java基础、Spring Boot、Spring Cloud、Mysql、Redis、Elasticsearch、中间件、架构设计、面试题、程序员攻略等

你可能感兴趣的:(java,guava,java)