Table of contents


Guava是google的一個開源項目,目的在提供常用工具類的API,字串處理,caching,primitives型別處理,I/O,併行(concurrnecy)處理, 還有超級好用的Collections處理。

本篇主要著重於Collection以外相關的使用介紹,Collection的使用介紹在另一篇

  1. Strings
    1. Joiner
    2. Splitter
    3. CharMatcher
  2. Basic Utilities
  3. Caches
  4. Concurrency
  5. Primitives
  6. Ranges
  7. Hashing
  8. EventBus
  9. Math

Strings

CharMatcher
CharMatcher.is('.').replaceFrom(aStr, '_');                                       // 將字串中的'.'換成'_'
CharMatcher.DIGIT.matchesAllOf("1231212");                                        // true
CharMatcher.DIGIT.matchesAnyOf("1231 aa212");                                     // true
CharMatcher.DIGIT.retainFrom("Hello 1234 567");                                   // "1234567";
CharMatcher.DIGIT.or(CharMatcher.WHITESPACE).retainFrom("Hello 1234 567");        // " 1234 567"
CharMatcher.inRange('3', '6').removeFrom("Hello 1234 567");                       // "Hello 12 7";
CharMatcher.is('$').trimFrom("$$$ This is a $ sign $$$");                         // " This is a $ sign "
CharMatcher.is('$').or(CharMatcher.is(' ')).trimFrom("$$$ This is a $ sign $$$"); // "This is a $ sign"

Joiner

字串相加

Joiner joiner = Joiner.on("; ").skipNulls();
return joiner.join("Harry", null, "Ron", "Hermione"); // "Harry; Ron; Hermione"
 
numbersWords.put(1, "one");
numbersWords.put(2, "two");
numbersWords.put(3, null);
numbersWords.put(4, "four");
Joiner.on(" | ").withKeyValueSeparator(" -> ")
    .useForNull("Unknown").join(numbersWords)); // 1 -> one | 2 -> two | 3 -> Unknown | 4 -> four"

Splitter

字串分割

Splitter.on(',')
       .trimResults()
       .omitEmptyStrings()
       .split("foo,bar,,   qux");

Basic Utilities

Optional (Null處理)

java對null的處理不是很友善,所以常常需要去對null值特別處理,而Optional就是用來處理null問題的利器。

// 是否是常看到這樣的code
if (foo == null) {
  // do something
} else {
  // do something
}
 
// servlet總會遇到這個
String username;
if (request.getParameter("username") == null) {
    username = "Stranger";
} else {
   username = request.getParameter("username");
}
 
// 或者
String username = request.getParameter("username") == null ? "Stranger" : request.getParameter("username");

如果改用Optional的話

Optional.of(request.getParameter("username")).or("default");

這個class我個人滿少用的,它的一些延伸用法不是很直覺

Preconditions

前置條件檢查,通常會在在method的最前面,用來保證參數或變數在一定的狀態,如果不在預期的狀況,就拋出異常。

  1. checkArgument(boolean) : 用來檢查method的參數,不為true則拋出 IllegalArgumentException
  2. checkNotNull(T) : 如果是 null 拋出 NullPointerException
  3. checkState(boolean) : 跟checkArgument(boolean)很像,但用來檢查非參數的變數,如果不為true,拋出 IllegalStateException
  4. checkElementIndex(int index, int size) : 用來檢查List,Array或字串index的合法性,不合法就拋出 IndexOutOfBoundsException
  5. checkPositionIndex(int index, int size) : 用來檢查List,Array或字串index的合法性,不合法就拋出 IndexOutOfBoundsException
  6. checkPositionIndexes(int start, int end, int size) : 用來檢查List,Array或字串index的合法性,不合法就拋出 IndexOutOfBoundsException

checkElementIndex,checkPositionIndex,checkPositionIndexes用法比較特別,它不需要傳入List,Array或字串本身,只需傳入List,Array或字串的index,size,或start,end

Ordering

排序用,如果要被排序的元素本身已有Comparator的話,可以直做透過Ordering做排序, 如果沒有,也可以extends Ordering達到排序的效果。

Object methods

傳統的Comparable實作方式很煩人,而且容易出錯

class Person implements Comparable<Person> {
  private String lastName;
  private String firstName;
  private int zipCode;
 
  public int compareTo(Person other) {
    int cmp = lastName.compareTo(other.lastName);
    if (cmp != 0) {
      return cmp;
    }
    cmp = firstName.compareTo(other.firstName);
    if (cmp != 0) {
      return cmp;
    }
    return Integer.compare(zipCode, other.zipCode);
  }
}

Guava提供ComparisonChain簡化Comparable.

   public int compareTo(Foo that) {
     return ComparisonChain.start()
         .compare(this.aString, that.aString)
         .compare(this.anInt, that.anInt)
         .compare(this.anEnum, that.anEnum, Ordering.natural().nullsLast())
         .result();
   }

Throwables

 try {
     someMethodThatCouldThrowAnything();
   } catch (IKnowWhatToDoWithThisException e) {
     handle(e);
   } catch (Throwable t) {
     Throwables.propagateIfInstanceOf(t, IOException.class);
     Throwables.propagateIfInstanceOf(t, SQLException.class);
     throw Throwables.propagate(t);
   }

Caches

Guava Cache很像Map,但在使用上跟行為上還是跟Map有許多不同之類。Guava Cache只會暫存在Memory(RAM),不會儲存 在local file system.

建立cache有兩種方式,一種是一開始就load所需要的資料,另一種是如果資料不存在就建立,否則就直接取cache內的資料

CacheLoader是在開始時就建立好cache的資料
LoadingCache<Key, Graph> graphs = CacheBuilder.newBuilder()
        .maximumSize(10000)
        .expireAfterWrite(10, TimeUnit.MINUTES)
        .removalListener(MY_LISTENER)
        .build(
            new CacheLoader<Key, Graph>() {
                public Graph load(Key key) throws AnyException {
                return createExpensiveGraph(key);
            }
        });

Callable是取不到資料時就建立cache

當執行cache.get,如果有cache就會從cache取,如果沒有cache就會建立一份到cache中

Cache<Key, Value> cache = CacheBuilder.newBuilder()
    .maximumSize(1000)
    .build(); // look Ma, no CacheLoader
...
try {
  // If the key wasn't in the "easy to compute" group, we need to
  // do things the hard way.
  cache.get(key, new Callable<Value>() {
    @Override
    public Value call() throws AnyException {
      return doThingsTheHardWay(key);
    }
  };
} catch (ExecutionException e) {
  throw new OtherException(e.getCause());
}

Concurrency

ListenableFuture Service Using Implementations Monitor

Primitives

Primitive arrays General utilities Byte conversion Unsigned support

Ranges

用來處理一個範圍內class,主要是透過Comparable來做範圍的運算, 所以不一定是要數值型的class才能做Range,像有實作Comparable的日期也是可以做範圍處理。

可透過Ranges類別來建立Range

Ranges.closed(1,10);

EventBus

EventBus是guava的事件處理,但不像傳統的Event-Listener那樣需要implement xxxListener那樣(結果就是產生了一堆inner class或anonymous inner class) 而是透過@Annotation的方式處理。

// Class is typically registered by the container.
class EventBusChangeRecorder {
  @Subscribe void recordCustomerChange(ChangeEvent e) {
    recordChange(e.getChange());
  }
}
// somewhere during initialization
eventBus.register(new EventBusChangeRecorder());
// much later
public void changeCustomer() {
  ChangeEvent event = getChangeEvent();
  eventBus.post(event);
}

Reference

  1. http://codingjunkie.net/guava-eventbus/
  2. http://tomaszdziurko.pl/2012/01/google-guava-eventbus-easy-elegant-publisher-subscriber-cases/

Math

TBD

Resources