Guava-2-基本Guava工具

Snapshot API Docs for Guava: https://guava.dev/releases/snapshot-jre/api/docs/

使用Joiner类

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.on("|").skipNulls().join(stringList);// return String

如果想用一个替代品代替null值,可以这样:

Joiner.on("|").useForNull("no value").join(stringList);

注意,Joiner类不是严格地只工作于strings,你可以传参为array、iterable、varargs of any Object。

返回结果是通过为每个传参元素调用Object.toString()完成的。但后果是如果没有使用skipNulls或useForNull,则会抛出NullPointerException异常。

一旦创建,一个Joiner类对象是不可变的(immutable),因此它是线程安全的(thread-safe),它可以使用static final修饰。记住这段话,然后看下面例子:

1. Joiner stringJoiner = Joiner.on("|").skipNulls();
2. stringJoiner.useForNull("missing");
3. stringJoiner.join("foo", "bar", null);

第1行,创建一个Joiner实例。第2行,是创建了一个【新的】Joiner实例。所以,第2行的useForNull()对原来的Joiner实例不起效果。第3行返回的结果是skipNulls()的效果。相当于是如下:(所以记住:Joiner类对象是不可变的(immutable))

1. Joiner stringJoiner = Joiner.on("|").skipNulls();
2. Joiner newStrJoiner = stringJoiner.useForNull("missing");
3. String newStr = stringJoiner.join("foo", "bar", null);

Joiner类也有方法appendTo()作用于StringBuiler:

StringBuilder stringBuilder = new StringBuilder();
Joiner joiner = Joiner.on("|").skipNulls();
joiner.appendTo(stringBuilder, "foo", "bar", "baz");// return StringBuilder instance

Joiner类还可用于实现了Appendable接口的对象:

Class FileWriter
  java.lang.Object
    java.io.Writer
      java.io.OutputStreamWriter
        java.io.FileWriter
All Implemented Interfaces:
Closeable, Flushable, 【Appendable】, AutoCloseable
FileWriter fileWriter = new FileWriter(new File("path"));
List<Date> dateList = getDates();
Joiner joiner = Joiner.on("#").useForNulls(" ");
joiner.appendTo(fileWriter, dateList);// return FileWriter instance

Joiner类append the joined list of dates to the FileWriter instance and then return the FileWriter instance。

MapJoiner类

MapJoiner mapJoiner = Joiner.on("#").withKeyValueSeparator("=");

Joiner.on("#")创建一个Joiner对象,然后调用withKeyValueSeparator方法,这时Joiner实例就构建一个MapJoiner对象。

下面是一个单元测试,证实MapJoiner方法的使用:

import java.util.Map;
import com.google.common.base.Joiner;
import com.google.common.collect.Maps;
import org.junit.Test;
import static org.junit.Assert.*;// 静态导入
import static org.hamcrest.CoreMatchers.*;// 静态导入

public class App {
	@Test
	public void testMapJoiner() {
	    String expectedString = "Washington D.C=Redskins#New York City=Giants#Philadelphia=Eagles#Dallas=Cowboys";
	    // 使用LinkedHashMap,原始插入的顺序被保留
	    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));
	}
}

对于JUnit,assertThat()<=>org.junit.Assert.assertThat(),is()<=>org.hamcrest.CoreMatchers.is()。


使用Splitter类

String testString = "Monday,Tuesday,,Thursday,Friday,,";
String[] parts = testString.split(",");

一个Splitter类可以操作单个字符、字符串、java.util.regex.Pattern、正则表达式、CharMather类。

Splitter.on('|').split("foo|bar|baz");
Splitter splitter = Splitter.on("\\d+");
Splitter splitter = Splitter.on('|').trimResults();// 删除任何开头或结尾的空格

就像Joiner类,Splitter在创建时是不可变的(immutable),所以要注意不要在创建了一个原始的Splitter类后,单独调用trimResults。

Splitter splitter = Splitter.on('|');
splitter.trimResults();// 创建一个新实例,不改变原始对象
Iterable<String> parts = splitter.split("1|2|3|||");// 结果仍然包含空元素

MapSplitter类

MapSplitter是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(startString);
	    assertThat(testMap, is(splitMap));
	}

在Guava中操作strings

使用Charsets类

byte[] bytes = someString.getBytes();

try {
        bytes = "foobarbaz".getBytes("UTF-8");
    } catch(UnsupportedEncodingException e) {
        // TODO
    }

如果系统的默认字符集不是你预期要去处理的,就会抛出异常。

注:UTF-8是Java平台必须支持的,所以上面UnsupportedEncodingException永远不会抛出。

Charsets类提供对6种字符集的static final引用。这样就不会出现拼写错误导致问题。

byte[] bytes = "foobarbaz".getBytes(Charsets.UTF_8);

使用Strings类

StringBuilder builder = new StringBuilder("foo");
char c = 'x';
for (int i=0; i<3;i++) {
    builder.append(c);
}
return builder.toString();

以上6行代码可以用下面1行代码替代:

Strings.padEnd("foo", 6, 'x');

第2个参数是返回的字符串的最小长度。

String.padStart("foo", 6, 'x'); 
=> xxxfoo

处理可能的null值:

nullToEmpty:如果string长度==0或string==null,返回"";否则返回原string。
emptyToNull:如果string长度==0或string==null,返回null;否则返回原string。
isNullOrEmpty:如果string长度==0或string==null,返回true;否则返回false。

使用CharMatcher类

下面代码将多行字符串用一个空格代替换行符,格式化为一条。

CharMatcher.BREAKING_WHITESPACE.replaceFrom(stringWithLinebreaks, ' ');

其中,stringWithLinebreaks可以是字符串也可以是CharSequence对象。

@Test
public void testRemoveWithWhiteSpace() {
    String tabsAndSpaces = "  String  with     spaces    and tabs";
    String expected = "String with spaces and tabs";
    String scrubbed = CharMatcher.WHITESPACE.collapseFrom(tabsAndSpaces, ' ');
    assert(scrubbed, is(excepted);
}

要删除任何开头或结尾的空格,用trimAndCollapseFrom方法就可以了。

如果我们要保持匹配的字符呢?

@Test
public void testRetainFrom() {
    String lettersAndNumbers = "foo989yxbar234";
    String expected = "989234";
    String retained = CharMatcher.JAVA_DIGIT.retainFrom(lettersAndNumbers);
    assertThat(expected, is(retained));
}

你还可以为numbers或whitespace创建一个matcher:

CharMatcher cm = CharMatcher.JAVA_DIGIT.or(CharMatcher.WHITESPACE);

使用Preconditions类

if (someObj == null) {
    throw new IllegalArgumentException("someObj must not be null");
}

通过使用Preconditions(使用静态导入),我们检查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) {
        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,则返回object,否则抛出NullPointerException。

checkElementIndex(int index, int size, Object message):size参数是array、list或string的长度。如果有效则返回index,否则抛出IndexOutOfBoundsException。

checkArgument(Boolean expression, Object message):Boolean表达式期望为true,否则抛出IllegalArgumentException。

checkState(Boolean expression, Object message):Boolean表达式期望为true,否则抛出IllegalArgumentException。


Object工具

生成toString有助于调试,但写一个是冗长乏味的。Objects类使用toStringHelper方法,使这项任务非常简单。

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();
    }
}

检查null值

String value = Objects.firstNonNull(someString, "default value");

如果不确定someString是否为null值,可以提供一个默认值。如果两个参数都为null,则抛出NullPointerException。

产生hash codes

public int hashCode() {
    return Objects.hashCode(title, author, publisher, isbn);
}

实现CompareTo

public int compareTo(Book o) {
    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());
}

现在用ComparisonChain类来实现compareTo:

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();
}

ComparisonChain类在遇到第一个非0结果后就会停止作比较。只有所有比较都为0结果才为0。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

itzyjr

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值