public String buildString(List<String> stringList, String delimiter){ StringBuilder builder = new StringBuilder(); for (String s : stringList) { if(s !=null){ builder.append(s).append(delimiter); } } builder.setLength(builder.length() – delimiter.length()); return builder.toString(); }
注意要删除在最后面的分隔符。不是很难懂,但是使用Joiner类可以得到简单的代码模板。同样的例子使用Joiner类代码如下:
public String buildString(List<String> stringList, String delimiter){ return Joiner.on(delimiter).skipNulls().join(stringList); }
这样更加简明并且不会出错。如果你想将null值替换掉,可以使用如下方法:
Joiner.on("|").useForNull("no value").join(stringList);
使用Joiner类有几点需要注意。Joiner类不仅仅可以处理字符串的array、list、iterable,他还可以处理任何对象的array、list、iterable。结果就是调用每一个元素的toString()方法。因此,如果没有使用skipNulls或者useForNull,就会抛出空指针异常。Joiner对象一旦被创建就是不可变的,所以他们是线程安全的,可以被当作常亮来看待。然后看看下面的代码片段:
Joiner stringJoiner = Joiner.on("|").skipNulls(); //使用useForNull方法将会返回一个新的Joiner实例 stringJoiner.useForNull("missing"); stringJoiner.join("foo","bar",null);
在上面的代码实例当中,useForNull方法并没有起作用,null值仍然报NPE了。
StringBuilder stringBuilder = new StringBuilder(); Joiner joiner = Joiner.on("|").skipNulls(); //返回的StringBuilder实例当中包含连接完成的字符串 joiner.appendTo(stringBuilder,"foo","bar","baz");
上面的例子,我们传入一个StringBuilder的参数并且返回一个StringBuilder实例。
FileWriter fileWriter = new FileWriter(new File("path")): List<Date> dateList = getDates(); Joiner joiner = Joiner.on("#").useForNulls(" "); // 返回由字符串拼接后的FileWriter实例 joiner.appendTo(fileWriter,dateList);
这是一个与上一个相似的例子。我们传入一个FileWriter实例和一组数据,就会将这组数据拼接后附加到FileWriter当中并且返回。
MapJoiner mapJoiner = Joiner.on("#").withKeyValueSeparator("=");
快速回顾一下上面内容:
- Joiner.on("#")方法会创建一个Joiner的实例。
- 使用返回的Joiner实例调用withKeyValueSeparator方法将会返回MapJoiner对象。
@Test public void testMapJoiner() { String expectedString = "Washington D.C=Redskins#New York City=Giants#Philadelphia=Eagles#Dallas=Cowboys"; Map<String,String> testMap = Maps.newLinkedHashMap(); testMap.put("Washington D.C","Redskins"); testMap.put("New York City","Giants"); testMap.put("Philadelphia","Eagles"); testMap.put("Dallas","Cowboys"); String returnedString = Joiner.on("#"). withKeyValueSeparator("=").join(testMap); assertThat(returnedString,is(expectedString)); }
回顾时间
String testString = "Monday,Tuesday,,Thursday,Friday,,"; //parts is [Monday, Tuesday, , Thursday,Friday] String[] parts = testString.split(",");
可以看到,String.split方法省略了最后的2个空串。在有些时候,这个做法是你需要的,但是这些事情是应该由程序员来决定是否省略。Splitter类可以帮助我们实现与Joiner类相反的功能。Splitter可以使用单个字符、固定字符串、正则表达式串、正则表达式对象或者CharMatcher对象(另一个Guava的类,本章会讲到)来分割字符串。可以给定具体分割符来创建Splitter对象然后使用。一旦拥有了Splitter实例后就可以调用split方法,并且会返回包含分割后字符串的迭代器对象。
Splitter.on('|').split("foo|bar|baz"); Splitter splitter = Splitter.on("\d+");
在上面的例子当中,我们看到一个Splitter 实例使用了'|'字符分割,另外一个实例使用了正则表达式进行分割。
//Splits on '|' and removes any leading or trailing whitespace Splitter splitter = Splitter.on('|').trimResults();
与Joiner类一样Splitter类同样是一个不可变的类,所以在使用的时候应该使用调用trimResults方法后返回的Splitter实例。
Splitter splitter = Splitter.on('|'); //Next call returns a new instance, does not modify the original! splitter.trimResults(); //Result would still contain empty elements Iterable<String> parts = splitter.split("1|2|3|||");
Splitter 类,像Joiner与MapJoiner一样也有MapSplitter类。MapSplitter类可以将字符串转换成Map实例返回,并且元素的顺序与字符串给定的顺序相同。使用下面方法构造一个MapSplitter实例:
//MapSplitter is defined as an inner class of Splitter Splitter.MapSplitter mapSplitter = Splitter.on("#"). withKeyValueSeparator("=");
@Test
public void testSplitter() {
String startString = "Washington D.C=Redskins#New York City=Giants#Philadelphia=Eagles#Dallas=Cowboys";
Map<String,String> testMap = Maps.newLinkedHashMap();
testMap.put("Washington D.C","Redskins");
testMap.put("New York City","Giants");
testMap.put("Philadelphia","Eagles");
testMap.put("Dallas","Cowboys");
Splitter.MapSplitter mapSplitter = Splitter.on("#").withKeyValueSeparator("=");
Map<String,String> splitMap = mapSplitter.split(startSring);
assertThat(testMap,is(splitMap));
}
- CharMatcher
- Charsets
- Strings
byte[] bytes = someString.getBytes();
try{ bytes = "foobarbaz".getBytes("UTF-8"); }catch (UnsupportedEncodingException e){ //This really can't happen UTF-8 must be supported }
- UTF-8在java平台 一定会被支持,所以UnsupportedEncodingException一定不会被抛出
- 一旦我们使用字符串指定字符集的定义,我们可以产生拼写错误然后导致异常抛出。
byte[] bytes2 = "foobarbaz".getBytes(Charsets.UTF_8);
StringBuilder builder = new StringBuilder("foo"); char c = 'x'; for(int i=0; i<3; i++){ builder.append(c); } return builder.toString();
Strings.padEnd("foo",6,'x');
- nullToEmpty:这个方法接受一个字符串参数,如果传入的参数不是null值或者长度大于0则原样返回,否则返回空串("");
- emptyToNull:这个方法类似于nullToEmpty,它将返回null值如果传入的参数是空串或者null。
- isNullOrEmpty:这个方法会检查传入参数是否为null和长度,如果是null和长度为0就返回true。
CharMatcher.BREAKING_WHITESPACE.replaceFrom(stringWithLinebreaks,' ');
@Test public void testRemoveWhiteSpace(){ String tabsAndSpaces = "String with spaces and tabs"; String expected = "String with spaces and tabs"; String scrubbed = CharMatcher.WHITESPACE.collapseFrom(tabsAndSpaces,' '); assertThat(scrubbed,is(expected)); }
@Test public void testTrimRemoveWhiteSpace(){ String tabsAndSpaces = " String with spaces and tabs"; String expected = "String with spaces and tabs"; String scrubbed = CharMatcher.WHITESPACE. trimAndCollapseFrom(tabsAndSpaces,' '); assertThat(scrubbed,is(expected)); }
@Test public void retainFromTest() { String lettersAndNumbers = "foo989yxbar234"; String expected = "989234"; String actual = CharMatcher.JAVA_DIGIT.retainFrom(lettersAndNumbers); assertEquals(expected, actual); }
CharMatcher cm = CharMatcher.JAVA_DIGIT.or(CharMatcher.WHITESPACE);
if(someObj == null){ throw new IllegalArgumentException(" someObj must not be null"); }
checkNotNull(someObj,"someObj must not be null");
public class PreconditionExample { private String label; private int[] values = new int[5]; private int currentIndex; public PreconditionExample(String label) { //返回label如果不为空 this.label = checkNotNull(label,"Label can''t be null"); } public void updateCurrentIndexValue(int index, int valueToSet) { //检查索引是否有效 this.currentIndex = checkElementIndex(index, values.length, "Index out of bounds for values"); //检查参数值 checkArgument(valueToSet <= 100,"Value can't be more than 100"); values[this.currentIndex] = valueToSet; } public void doOperation(){ checkState(validateObjectState(),"Can't perform operation"); } private boolean validateObjectState(){ return this.label.equalsIgnoreCase("open") && values[this. currentIndex]==10; } }
- checkNotNull(T object, Object message):这个方法如果object不为null直接返回,如果为null会抛出空指针异常。
- checkElementIndex (int index, int size, Object message):在这方法当中,index是你将要访问的元素下标,size是这个要访问的array,list或者字符串的长度。然后校验是否有效,如果无效抛出IndexOutOfBoundsException。
- checkArgument (Boolean expression, Object message):这方法传入布尔表达式。 这个布尔表达式如果为true则继续执行,否则抛出IllegalArgumentException。
- checkState (Boolean expression, Object message):这方法传入 一个布尔表达式涉及对象的状态,而不是参数。 这个布尔表达式如果为true则继续执行,否则抛出IllegalArgumentException。
public class Book implements Comparable<Book> { private Person author; private String title; private String publisher; private String isbn; private double price; public String toString() { return Objects.toStringHelper(this).omitNullValues().add("title", title).add("author", author).add("publisher", publisher) .add("price",price).add("isbn", isbn).toString(); } }
- 首先我们传入一个Book对象来创建一个Objects.ToStringHelper实例。
- 第二步,我们调用omitNullValues来排除任何null值的属性。
- 调用add方法来添加每一个属性的标签和属性。
String value = Objects.firstNonNull(someString, "default value");
public int hashCode() { return Objects.hashCode(title, author, publisher, isbn); }
int result = this.title.compareTo(o.getTitle()); if (result != 0) { return result; } result = this.author.compareTo(o.getAuthor()); if (result != 0) { return result; } result = this.publisher.compareTo(o.getPublisher()); if(result !=0 ) { return result; } return this.isbn.compareTo(o.getIsbn()); }
public int compareTo(Book o) { return ComparisonChain.start() .compare(this.title, o.getTitle()) .compare(this.author, o.getAuthor()) .compare(this.publisher, o.getPublisher()) .compare(this.isbn, o.getIsbn()) .compare(this.price, o.getPrice()) .result(); }