Guava库之字符串操作

Guava是google推出的一个类库,包含了很多个模块,今天先学习一下其中字符串处理相关的工具类。
通过Maven将Guava的jar包获取到本地,同时获取到其源码和doc文档,将doc文档解压打开后对该类库有一个大概的了解。
字符串相关的处理基本都在com.google.common.base包下,而其中与字符串处理相关的类包含如下几个:
这里写图片描述

Strings

Strings类提供了一些静态方法,用于进行一些日常遇到的字符串处理工作,其参数为CharSequence或者String类型。
其中CharSequence是一个interface,该接口对字符序列提供了统一的、只读的读取;该接口没有重新定义Object的equals和hashCode方法,因此该接口的实现对象可以按需实现自己的这两个方法。
String,StringBuilder,StringBuffer都实现了该接口。
Strings类中提供了如下的方法:
这里写图片描述
其中最后一个方法是非public方法,其他的public方法可以分为以下四类:
①null,empty的处理:
nullToEmpty:若为null,则返回空串;否则返回原字符串;
emptyToNull:若为null或”“,则返回null;否则返回原字符串;
isNullOrEmpty:是否为null或”“;
②字符串补齐的处理
padStart:在字符串前append提供的字符,以达到指定长度;
padEnd:在字符串后append提供的字符,以达到指定长度;
③重复方式构造新字符串:
repeat:将给定字符串重复给定次数后返回新串;
④判断是否有相同前缀,相同后缀:
commonPrefix:返回两个CharSequence最长的共同的前缀;
commonSuffix:返回两个CharSequence最长的共同的后缀;

查看源码的时候有一些需要关注和学习的地方:
①如下是repeat方法中的一段,这一段的目的在于判断将String重复n次之后,是否超长了。而其方法则是先将int向上转型为long,后将long向下转型为int,再判断二者是否相等。这样,如果在超长的情况下,将出现截断;

    final int len = string.length();
    final long longSize = (long) len * (long) count;
    final int size = (int) longSize;
    if (size != longSize) {
      throw new ArrayIndexOutOfBoundsException(
          "Required array size too large: " + longSize);
    }

②另外就是那个私有方法:注解表示该方法仅仅在测试代码中可用;而其逻辑中的surrogate pair这个东西是Java的UTF-16 Unicode编码的一个术语,这种编码方式也有一定的范围限制,从0x0000到0xFFFF,这个方法判断的是字符是否超出了这个范围。

@VisibleForTesting
  static boolean validSurrogatePairAt(CharSequence string, int index) {
    return index >= 0 && index <= (string.length() - 2)
        && Character.isHighSurrogate(string.charAt(index))
        && Character.isLowSurrogate(string.charAt(index + 1));
  }

Joiner

Joiner提供了一些方法,用于将文本进行连接,这些文本可以存放在数组中,Iterable接口实现类中,变长参数列表中,甚至是Map中。
这里写图片描述
Joiner的方法可以分为如下几种类型:
①Joiner的构造函数是private的,所以不能直接new一个Joiner出来,而是通过静态方法on来创建一个Joiner(其参数为用于标识字符串分隔符的char或者String);
②appendTo方法,该方法用于将要连接的内容接续到Appendable或者StringBuilder后面:
该方法一共有8个重载,根据返回参数类型不同分为两种,一种是以Appendable接口泛型为参数,另一种以StringBuilder为参数。(这里一个疑问就是StringBuilder也是实现了Appendable接口的,是通过其父类AbstractStringBuilder实现的,那么在以StringBuilder作为参数的时候,是否会发生歧义呢?这个可能要研究一下泛型相关内容了);
在这两种不同情况下,传递进来的用于进行Join的参数类型分别有Iterable,Iterator,Object[]以及变长参数。
这里写图片描述
实现了Iterable接口的容器可以执行forEach操作,另外它可以返回迭代器Iterator。
这里写图片描述
迭代器用于遍历Iterable容器。
③join方法,该方法用于进行内容连接,其参数也可以是Iterable,Iterator,Object[]以及变长参数。
join方法其实还是调用的appendTo,会默认构造一个StringBuilder作为appendTo的第一个参数。
另外要注意的是:join方法返回类型为String。
④两个装饰者方法,返回新Joiner:
useForNull:当进行连接的时候,如果某个元素为null,则用指定的替代文本代替;
skipNulls:跳过null值;
这里要注意Joiner是immutable的,也就是说不能在Joiner创建后再行改变其行为,所以useForNull和skipNulls不是改变已有的Joiner实例的行为,而是创建一个新的Joiner;
⑤withKeyValueSeparator:这个方法返回一个MapJoiner,这是一个静态内部类。
这里写图片描述
该类的实例需要通过withKeyValueSeparator生成,也就是通过Joiner的on方法生成一个Joiner实例后,再调用withKeyValueSeparator方法生成一个MapJoiner实例。
MapJoiner的方法与Joiner基本相似,但其处理的容器是Map,或者Map.Entry的Iterable/Iterator。它有一个成员keyValueSeparator用来标识Map的Key-Value之间通过什么分隔符进行连接,而原先的Joiner的成员变量separator则用来标识不同的键值对之间用什么进行连接。

Splitter

Splitter类用来将CharSequence以给定的分隔符进行分割后组装成为Iterable、Iterator或者List。
该类的实现模式与Joiner很相似。
这里写图片描述
①首先要了解一下Splitter的几个成员变量:
strategy:Strategy是一个内部接口,用于生成一个泛型类型参数为String的Iterator;该成员一般在构造函数中通过匿名类的方式创建并赋给成员变量。在执行最终的split方法的时候要生成Iterable或者List时,会调用strategy的iterator方法来实现最终生成的Iterable或者List的iterator方法。
trimmer:这是一个CharMatcher类实例,在调用trimResults方法的时候作为参数传递进来,用于在对字符串进行分割的时候,对每一个成员进行前后字符的trim处理(如果trimmer这个CharMatcher执行matches为true,则把对应字符trim掉后加入Iterable或者List)。
omitEmptyStrings:这个成员容易理解,就是是否忽略空串;
limit:这个成员表示最多分割成多少个成员,满足数目要求后,最后剩下的部分会作为一个整体成为一个成员。
②静态抽象内部类SplittingIterator:
该类继承自AbstractIterator,实现了Iterator接口。
这个类就是用来生成最后的Iterable或者List所用的迭代器,其内部用来迭代容器元素。在其computeNext方法中会计算接下来的元素是什么。
③on方法:该方法有4个重载,传入的参数分别是char,CharMatcher,String,Pattern,用作分隔符。
④几个修饰性方法:
fixedLength:返回将字符串分割成为等长的几个字符串的Splitter;
omitEmptyStrings:返回忽略空串的Splitter;
limit:返回结果是limit长度容器的Splitter;
trimResults:返回的容器中的元素经过了指定的trim处理的Splitter;
⑤真正执行分割的方法:
split:返回Iterable类型;
splitToList:返回List类型;
⑥MapSplitter:
同样的,也有针对Map的Splitter,返回的结果是Map,不再赘述。
这个类的源码中还是有不少值得探索的地方,有空深究一下。

CharMatcher

在Splitter中已经用到过CharMatcher。这个类就是用来判定某个char是否满足相应的判断。
这里写图片描述
首先看一下这些静态类成员,都是CharMatcher类型的。
DIGIT:判断某个char是否是数字,这个数字包含了各种语言的数字表达;
JAVA_DIGIT:
JAVA_LETTER:
JAVA_LETTER_OR_DIGIT:
JAVA_UPPER_CASE:
JAVA_LOWER_CASE:
以上几个都是通过Character的相关方法进行判断;
JAVA_ISO_CONTROL:
INVISIBLE:
SINGLE_WIDTH:
ANY:匹配所有;
NONE:什么都不匹配;
①一些静态的生成CharMatcher的方法:
这里写图片描述
以上方法都很容易理解,其实都是Override了CharMatcher的相关抽象方法生成一个新的CharMatcher,不赘述了;
②另一些静态的生成CharMatcher的方法:
这里写图片描述
③真正判断是否匹配的方法matches;
④一些只读的获取信息的方法:
这里写图片描述
⑤一些提取所需信息或者按照匹配规则修饰处理后获得结果的方法:
这里写图片描述

Charsets

Charsets定义了一些常见编码;这个在Java7以上要deprecated了,不分析了。

CaseFormat

CaseFormat定义了一些常见的标识符命名模式,如“小写以-分割”,“小写以分割”,“小写打头的骆驼”,“大写打头的骆驼”,“大写以分割”。
CaseFormat是个枚举类型,提供了一个抽象方法normalizeWord,用来给它的枚举值进行Override。
该枚举提供了一个to方法用来将指定字符串进行格式转换。

以上这些类提供了很多我们日常工作中需要进行的字符串操作的实现,我们无需再重复造轮子,而且有可能造得还不好!需要做的,就是在工作中遇到相应场景的时候,想起来我们还有这么一些工具类可以利用!

猜你喜欢

转载自blog.csdn.net/achang07/article/details/79287553