Guava字符串处理 字符串不管在什么时候都是我们最为关心的,尤其是从事Web开发的朋友,字符串的各种操作也都是工作中必备的技能。Google也看到了我们广大的开发者处理字符串的痛点,于是他们为我们带来了Strings
的工具类,这个工具类套件包含了很多有用的类,比如Strings
类本身,还有用于分割的Splitter
类,用于连接的Joiner
类以及用于字符串匹配的CharMatcher
类等等。下面我们就针对这些类进行详细的说明。
Strings类使用实例 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 package com.qinjiangbo;import com.google.common.base.Strings;import org.junit.Test;public class StringsTest { @Test public void testNullOrEmptyString () { System.out.println(Strings.isNullOrEmpty("" )); } @Test public void testNullOrEmptyString2 () { System.out.println(Strings.isNullOrEmpty(null )); } @Test public void testStringsPadEnd () { System.out.println(Strings.padEnd("Hello World" , 20 , '-' )); } @Test public void testStringsPadStart () { System.out.println(Strings.padStart("Hello World" , 20 , '*' )); } @Test public void testStringsRepeat () { System.out.println(Strings.repeat("I love you!\n" , 20 )); } }
上面的代码中的测试方法都是自解释型的,所以我就不一一做详细的介绍了。不过需要解释一下其中的pad相关的方法,pad就是padding的简写,有两个方法padStart
和padEnd
,这两个方法说的是字符串的偏移,案例中Strings.padStart("Hello World", 20, '*')
是从起始位置向右偏移,左边空出来的位置使用*
号填充,同理,Strings.padEnd("Hello World", 20, '-')
是从起始位置向左边偏移,右边空出来的部分使用-
填充。
Splitter类使用实例 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 package com.qinjiangbo;import com.google.common.base.CharMatcher;import com.google.common.base.Splitter;import com.google.common.collect.Lists;import org.junit.Test;import java.util.List;public class SplitterTest { @Test public void testSplitOnSemicolons () { Iterable<String> iterable = Splitter.on(";" ).split("Java;Scala;Php;Haskell" ); List<String> splittedList = Lists.newArrayList(iterable); System.out.println(splittedList.get(2 ).equals("Php" )); } @Test public void testSplitOnRegExp () { Iterable<String> iterable = Splitter.onPattern("\\d+" ).split("Java13Scala41Php5C#6" ); List<String> splittedList = Lists.newArrayList(iterable); System.out.println(splittedList.get(2 ).equals("Php" )); } @Test public void testSplitUsingCharMatcher () { Iterable<String> iterable = Splitter.on(CharMatcher.inRange('3' , '8' )).split("Java3Scala4Haskell7Brain9Kotlin" ); List<String> splittedList = Lists.newArrayList(iterable); System.out.println(splittedList.get(3 )); } @Test public void testSplitOmitEmptyStrings () { Iterable<String> iterable = Splitter.on(";" ).omitEmptyStrings().split("Java;Scala; ;;Haskell;;Kotlin" ); List<String> splittedList = Lists.newArrayList(iterable); System.out.println(splittedList.get(2 )); } @Test public void testSplitTrimResults () { Iterable<String> iterable = Splitter.on(";" ).trimResults().omitEmptyStrings().split("Java;Scala; ;;Haskell;;Kotlin" ); List<String> splittedList = Lists.newArrayList(iterable); System.out.println(splittedList.get(2 )); } @Test public void testSplitOnFixedLength () { Iterable<String> iterable = Splitter.fixedLength(7 ).split("Someone once told me that I was lucky!" ); List<String> splittedList = Lists.newArrayList(iterable); System.out.println(splittedList.get(1 )); } }
我们很容易从这个类的名字知道,这个类是用来分割字符串的,其实Java中的String
类也可以分割字符串,比如String.split()
方法,但是为什么我们要使用Guava的Splitter
类呢?原因很简单,因为它更简单而且更强大!上面的测试方法也都是自解释型的,所以我还是只打算解释其中一两个测试方法的使用。testSplitUsingCharMatcher
这个方法使用了我们即将要介绍的CharMatcher
类,这个类能极大地提升这个分割的灵活性和多样性,基本上能涵盖我们平时开发中的所有要求。关于CharMatcher
类具体的使用方式我们接下来介绍。
CharMatcher类使用实例 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 package com.qinjiangbo;import com.google.common.base.CharMatcher;import org.junit.Test;public class CharMatcherTest { @Test public void testNotMatchChar () { System.out.println(CharMatcher.noneOf("xZ" ).matchesAnyOf("anything" )); } @Test public void testMatchAny () { System.out.println(CharMatcher.ANY.matchesAllOf("anything" )); } @Test public void testMatchBreakingWhiteSpace () { System.out.println(CharMatcher.BREAKING_WHITESPACE.matchesAllOf("\r\n\r\n" )); } @Test public void testMatchDigits () { System.out.println(CharMatcher.DIGIT.matchesAllOf("1212121" )); } @Test public void testMatchDigits2 () { System.out.println(CharMatcher.DIGIT.matchesAnyOf("123abc123" )); } @Test public void testMatchJavaDigits () { System.out.println(CharMatcher.JAVA_DIGIT.matchesAllOf("123456" )); } @Test public void testMatchJavaLetter () { System.out.println(CharMatcher.JAVA_LETTER.matchesAllOf("Opera" )); } @Test public void testMatchAscii () { System.out.println(CharMatcher.ASCII.matchesAllOf("azt*1" )); } @Test public void testMatchUpperCase () { System.out.println(CharMatcher.JAVA_UPPER_CASE.matchesAllOf("JAVAC" )); } @Test public void testMatchDigitsWithWhiteSpaces () { System.out.println(CharMatcher.DIGIT.matchesAnyOf("1111 abc" )); } @Test public void testMatchRetainsDigits () { System.out.println(CharMatcher.DIGIT.retainFrom("123gb6789" )); } @Test public void testMatchRetainsDigitsOrWhiteSpaces () { System.out.println(CharMatcher.DIGIT.or(CharMatcher.WHITESPACE).retainFrom("Hello world 123 javac!" )); } @Test public void testMatchRetainsNothingAsConstrainsAreExcluding () { System.out.println(CharMatcher.DIGIT.and(CharMatcher.JAVA_LETTER).retainFrom("hello 123 abc!" )); } @Test public void testMatchRetainsDigitsAndLetters () { System.out.println(CharMatcher.DIGIT.or(CharMatcher.JAVA_LETTER).retainFrom("hello 123 abc!" )); } @Test public void testMatchCollapseAllDigitsByX () { System.out.println(CharMatcher.DIGIT.collapseFrom("Hello 167 j176" , 'x' )); } @Test public void testMatchReplaceAllDigitsByX () { System.out.println(CharMatcher.DIGIT.replaceFrom("Hello 17689 jik009" , 'x' )); } @Test public void testMatchReplaceAllLettersByX () { System.out.println(CharMatcher.JAVA_LETTER.or(CharMatcher.is('*' )).replaceFrom("password 97321321 **65" , 'X' )); } @Test public void testMatchCountIn () { System.out.println(CharMatcher.DIGIT.countIn("*** 121 * a ** b" )); } @Test public void testMatchCountIn2 () { System.out.println(CharMatcher.is('*' ).countIn("*** 121 * a ** b" )); } @Test public void testMatchIndexIn () { System.out.println(CharMatcher.is('*' ).indexIn("666 *** 121 * a ** b" )); } @Test public void testMatchLastIndexIn () { System.out.println(CharMatcher.is('*' ).lastIndexIn("666 *** 121 * a ** b" )); } @Test public void testMatchRemoveDigitsBetween3And6 () { System.out.println(CharMatcher.inRange('3' , '8' ).removeFrom("117787321daa096aa453aa299" )); } @Test public void testNegateMatchingAbove () { System.out.println(CharMatcher.inRange('3' , '8' ).negate().removeFrom("117787321daa096aa453aa299" )); } @Test public void testRemoveStartingAndEndingDollarsAndKeepOthersUnchanged () { System.out.println(CharMatcher.is('$' ).trimFrom("$$$ This is a $ sign $$$" )); } @Test public void testRemoveOnlyStartingDollarsAndKeepOthersUnchanged () { System.out.println(CharMatcher.is('$' ).trimLeadingFrom("$$$ This is a $ sign $$$" )); } @Test public void testRemoveOnlyEndingDollarsAndKeepOthersUnchanged () { System.out.println(CharMatcher.is('$' ).trimTrailingFrom("$$$ This is a $ sign $$$" )); } @Test public void testRemoveStartingAndEndingDollarsAndReplaceOtherDollarsWithX () { System.out.println(CharMatcher.is('$' ).trimAndCollapseFrom("$$$ This is a $$ and $ sign $$$" , 'X' )); } }
CharMatcher
为我们提供了非常强大的处理字符串的能力,可以看到CharMatcher
类基本上涵盖了我们操作字符串的各种方式。大家可以仔细看看上面的测试实例,并且好好琢磨琢磨它的使用方式。
Joiner类使用实例 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 package com.qinjiangbo;import com.google.common.base.Joiner;import com.google.common.collect.Maps;import org.junit.Test;import java.util.Arrays;import java.util.List;import java.util.Map;public class JoinerTest { @Test public void testJoinerOn () { List<String> languages = Arrays.asList("Java" , "Haskell" , "Scala" , "Brainfuck" ); System.out.println(Joiner.on(',' ).join(languages)); } @Test public void testJoinerJoinWithCommasAndOmitNulls () { List<String> countriesWithNullValue = Arrays.asList("Poland" , "Brazil" , "Ukraine" , null , "China" ); System.out.println(Joiner.on(',' ).skipNulls().join(countriesWithNullValue)); } @Test public void testJoinerJoinWithCommasAndReplaceNullWithDefaultValue () { List<String> countriesWithNullValue = Arrays.asList("Poland" , "Brazil" , "Ukraine" , null , "China" ); System.out.println(Joiner.on(',' ).useForNull("NONE" ).join(countriesWithNullValue)); } @Test public void testJoinerJoinMap () { Map<Integer, String> numberWords = Maps.newHashMap(); numberWords.put(1 , "one" ); numberWords.put(2 , "two" ); numberWords.put(3 , null ); numberWords.put(4 , "four" ); System.out.println(Joiner.on(" | " ).withKeyValueSeparator(" -> " ).useForNull("Unknown" ).join(numberWords)); } }
需要说明一下最后一个测试方法,这个是将Joiner类应用到了Map上面,我们可以利用Joiner类将Map表现形式转换成为我们想要的形式,这样更加易于读和理解。
总结 好了,Guava中的Strings相关的操作类在上面已经用实例代码进行了说明,每段代码都给出了相应的输出,测试全部通过。大家可以将上面的代码拷贝下来,自己到本机上跑一下,感受一下这段代码给我们带来的便捷与强大的操作能力。总的来说,Guava中涉及到字符串操作相关的类还有很多,这里不一一列出了。因为那些都没有上面列出的这些类方便和强大。我们主要是关注主要的类,我建议读者朋友们有时间自己还是多跑一跑上面的这些代码,更好地就是自己能动手敲一遍,这样更能加深自己的理解。