字符串工具
Joiner
用分隔符将一序列字符串连接到一起可能会有不必要的麻烦 – 但是不应该这样。如果你的序列包含null,它可能更加困难。Joiner
的流式风格简化这些操作。
Joiner joiner = Joiner.on("; ").skipNulls();
return joiner.join("Harry", null, "Ron", "Hermione");
返回字符串“Harry; Ron; Hermione”。或者,使用skipNulls
代替,你可以指定一个字符串来使用useForNull(String)
代替null。
你也可以在对象上使用Joiner
,他们将使用他们的toString
进行转换并进行连接。
Joiner.on(",").join(Arrays.asList(1, 5, 7)); // returns "1,5,7"
警告:Joiner实例总是不可变的。joiner配置方法总是返回一个新的Joiner
,你必须使用它获取所需的语义。这使任何Joiner
线程安全,并且可用作static final
常量。
Splitter
在Java构建中用于分割字符串的工具有一些古怪的行为。例如,String.split
悄悄地丢弃尾部分隔符,而且StringTokenizer
仅考虑五个空白字符,仅此而已。
小测试:",a,,b,".split(",")
返回什么?
"", "a", "", "b", ""
null, "a", null, "b", null
"a", null, "b"
"a", "b"
- 以上都没有
正确的答案是以上都没有:"", "a", "", "b"
。只有尾部的空字符串被忽略。这是什么?我都不知道。
Splitter
允许完全控制所有令人费解的行为,使用一个令人放心的直接的流式模式:
Splitter.on(',')
.trimResults()
.omitEmptyStrings()
.split("foo,bar,, qux");
返回一个Iterable<String>
,其包含"foo", “bar”, “qux”。Splitter
可以被设置依据任何Pattern
,char
,String
,CharMatcher
上进行分割。
基本工厂
方法 | 描述 | 示例 |
---|---|---|
Splitter.on(char) | 在特定的,单独的字符的出现上分割 | Splitter.on(';') |
Splitter.on(CharMatcher) | 在一些分类中的任何字符的出现上分割 | Splitter.on(CharMatcher.BREAKING_WHITESPACE) Splitter.on(CharMatcher.anyOf(";,.")) |
Splitter.on(String) | 在确切的String 上进行切割 | Splitter.on(", ") |
Splitter.on(Pattern) Splitter.onPattern(String) | 在正则表达式上分割 | Splitter.onPattern("\r?\n") |
Splitter.fixedLength(int) | 分割字符串为指定固定长度的子字符串。最后的片段可以小于length ,但永远不会为空 | Splitter.fixedLength(3) |
修饰符
方法 | 描述 | 示例 |
---|---|---|
omitEmptyStrings() | 自动忽略结果的空字符串 | Splitter.on(',').omitEmptyStrings().split("a,,c,d") 返回"a", "c", "d" |
trimResults() | 减去结果的头尾空白符;等价于trimResults(CharMatcher.WHITESPACE) 。 | Splitter.on(',').trimResults().split("a, b, c, d") 返回"a", "b", "c", "d" |
trimResults(CharMatcher) | 减去结果匹配指定的CharMatcher 的头尾 | Splitter.on(',').trimResults(CharMatcher.is('_')).split("_a ,_b_ ,c__") 返回"a ", "b_ ", "c" |
limit(int) | 返回了指定数量的字符串后停止分割 | Splitter.on(',').limit(3).split("a,b,c,d") 返回"a", "b", "c,d" |
如果你希望得到List
,使用splitToList()
代替split()
。
警告:分割器实例总是不可变的。分割器配置方法总是返回一个新的Splitter
,你必须使用它来获取所需的语义。这使任何Splitter
线程安全,可用作为static final
常量。
Map Splitters
你也可以使用一个splitter来反序列化一个map,通过使用withKeyValueSeparator()
指定第二个分隔符。作为结果的MapSplitter
使用splitter的分隔符将输入分割为条目(entry),然后使用给定的key-value分割器将这些条目分割到key和value,返回Map<String, String>
。
CharMatcher
在早期,我们的StringUtil
类不受约束地发展,有许多像以下这样的方法:
allAscii
collapse
collapseControlChars
collapseWhitespace
lastIndexNotOf
numSharedChars
removeChars
removeCrLf
retainAllChars
strip
stripAndCollapse
stripNonDigits
他们表示了两个概念的交集:
- 什么构成"匹配"字符?
- 如何处理这些“匹配”字符?
为了简化这个困境,我们开发了CharMatcher
。
直观地,你可以想象CharMatcher
作为表示一个特别的字符类,就像数字或者空格。实际上来说,CharMatcher
仅仅是在字符上的布尔(boolean)条件 – 实际上,CharMatcher
实现了Predicate<Character>
– 但是因为它通常适用于“所有空白字符”或者“所有小写字母”,Guava针对字符提供了特殊化语法和API。
但是CharMatcher
的效用是它允许你在指定类型的字符的出现执行操作:剔除(trimming),压缩(collapsing),移除(removing),保留(retaining)和更多操作。类型CharMatcher
对象表示概念1:什么构成了匹配字符串?然后它给出了很多回答概念2的操作:如何处理这些匹配字符串?结果是API的复杂性呈直线上升,灵活性和功能成倍增加。Yay!
String noControl = CharMatcher.javaIsoControl().removeFrom(string); // remove control characters
String theDigits = CharMatcher.digit().retainFrom(string); // only the digits
String spaced = CharMatcher.whitespace().trimAndCollapseFrom(string, ' ');
// trim whitespace at ends, and replace/collapse whitespace into single spaces
String noDigits = CharMatcher.javaDigit().replaceFrom(string, "*"); // star out all digits
String lowerAndDigit = CharMatcher.javaDigit().or(CharMatcher.javaLowerCase()).retainFrom(string);
// eliminate all characters that aren't digits or lowercase
注意:CharMatcher
只处理char
值;它不会理解附加附加在0x10000到0x10FFFF的Unicode代码点。这样的逻辑字符串使用代理对的方式编码到String
,CharMatcher
将这些仅视为两个分隔的字符。
获取CharMatcher
通过提供的CharMatcher
工厂方法可以满足许多需求:
any()
none()
whitespace()
breakingWhitespace()
invisible()
digit()
javaLetter()
javaDigit()
javaLetterOrDigit()
javaIsoControl()
javaLowerCase()
javaUpperCase()
ascii()
singleWidth()
其他获取CharMatcher
常用的方式包括:
方法 | 描述 |
---|---|
anyOf(CharSequence) | 指定所有你希望匹配的字符。例如,CharMatcher.anyOf("aeiou") 匹配小写英文元音 |
is(char) | 精确指定匹配的一个字符 |
inRange(char, char) | 指定匹配的范围字符,即:CharMatcher.inRange('a', 'z') |
或者,CharMatcher
有negate()
,and(CharMatcher)
和or(CharMatcher)
。这些提供关于CharMatcher
的布尔操作。
使用CharMatcher
CharMatcher
提供大量的方法来对在任何CharSequence
特定字符串的出现进行操作。提供了比我们在这里列出的更多的方法,但是一些最常用的是:
方法 | 描述 |
---|---|
collapseFrom(CharSequence, char) | 将每组连续的匹配字符串替换为指定的字符。例如,WHITESPACE.collapseFrom(string, ' ') 压缩空白符为单个空格 |
matchesAllOf(CharSequence) | 测试是否匹配器匹配在序列中的所有字符。例如,ASCII.matchesAllOf(string) 测试是否所有字符串中的字符是ASCII。 |
removeFrom(CharSequence) | 从序列中移除匹配的字符 |
retainFrom(CharSequence) | 从序列中移除所有非匹配字符 |
trimFrom(CharSequence) | 移除头部和尾部匹配的字符 |
replaceFrom(CharSequence, CharSequence) | 使用给定的序列替换匹配的字符 |
(注意:所有这些方法返回String
,除了matchesAllOf
,其返回boolean
。)
Charsets
不要这么做:
try {
bytes = string.getBytes("UTF-8");
} catch (UnsupportedEncodingException e) {
// how can this possibly happen?
throw new AssertionError(e);
}
这样做代替:
bytes = string.getBytes(Charsets.UTF_8);
Charsets
提供六个标准的Charset
实现的常量引用,保证所有Java平台实现支持。使用他们代替根据他们名称的字符编码引用。
TODO:charset说明和什么时候使用他们
(**注意:**如果你使用JDK7,你应该使用在StandardCharsets
中的常量。)
CaseFormat
CaseFormat
是一个用于ASCII大小写约定之间进行转换的小巧的类–例如,程序语言命名规范。支持的格式包含:
格式 | 示例 |
---|---|
LOWER_CAMEL | lowerCamel |
LOWER_HYPHEN | lower-hyphen |
LOWER_UNDERSCORE | lower_underscore |
UPPER_CAMEL | UpperCamel |
UPPER_UNDERSCORE | UPPER_UNDERSCORE |
使用它是相对简单的:
CaseFormat.UPPER_UNDERSCORE.to(CaseFormat.LOWER_CAMEL, "CONSTANT_NAME")); // returns "constantName"
我们发现这个特别有用,例如,当写生成其他程序的程序时。
Strings
存在于Strings
类中有限数量的通用目的的String
工具。