Thursday, December 5, 2013

Learning Guava Source Code



Ordering 是一个特殊的Comparator 实例。然而由于其良好的扩展性,可轻轻松构造复杂的comparator,比如加强型的容器的比较、排序等等;同时,Ordering提供链式方法调用,使用代码非常简洁漂亮。
Ordering<String> ordering = Ordering.from(String.CASE_INSENSITIVE_ORDER);
ordering.compare("A", "a")

链式比较

Ordering<String> ordering = Ordering.natural().nullsFirst().reverse().lexicographical().reverse().nullsLast();
ordering.sortedCopy(list);

Collection排序比较

Ordering<String> ordering = = Ordering.nullsFirst().reverse();
Collections.sort(names, ordering);

Ordering 详解

创建排序器

方法描述
natural()对可排序类型做自然排序,如数字按大小,日期按先后排序
usingToString()按对象的字符串形式做字典排序[lexicographical ordering]
from(Comparator)把给定的Comparator转化为排序器

链式调用方法

方法描述
reverse()获取语义相反的排序器
nullsFirst()使用当前排序器,但额外把null值排到最前面
nullsLast()使用当前排序器,但额外把null值排到最后面
compound(Comparator)合成另一个比较器,以处理当前排序器中的相等情况
lexicographical()基于处理类型T的排序器,返回该类型的可迭代对象Iterable<T>的排序器
onResultOf(Function)对集合中元素调用Function,再按返回值用当前排序器排序

运用排序器

方法描述
greatestOf(Iterable iterable, int k)获取可迭代对象中最大的k个元素
isOrdered(Iterable)判断可迭代对象是否已按排序器排序:允许有排序值相等的元素
sortedCopy(Iterable)判断可迭代对象是否已严格按排序器排序:不允许排序值相等的元素
min(E, E)返回两个参数中最小的那个。如果相等,则返回第一个参数
min(E, E, E, E...)返回多个参数中最小的那个。如果有超过一个参数都最小,则返回第一个最小的参数
min(Iterable)返回迭代器中最小的元素。如果可迭代对象中没有元素,则抛出NoSuchElementException

链式简洁风的实现原理

  • 基类
基类采用上述静态函数得到实例后,调用自身各种排序算法的接口获取新的排序实例,而接口中采用new子类实例获取,示例如下:
public abstract class Ordering<T> implements Comparator<T> {
    public <S extends T> Ordering<S> reverse() {
        return new ReverseOrdering<S>(this);
      }
    ......
}
  • 子类
子类负责特定的排序算法,示例如下:
final class ReverseOrdering<T> extends Ordering<T> implements Serializable {
     ReverseOrdering(Ordering<? super T> forwardOrder) {
        this.forwardOrder = checkNotNull(forwardOrder);
      }
    ......
}

总结

Guava的Ordering非常好的扩展性,较易扩展为复杂业务的比较器,且提供流行的链式风格,写代码如写文章,读代码如读美文.

Guava overflow detection
public static long checkedAdd(long a, long b) {
long result = a + b;
checkNoOverflow((a ^ b) &lt; 0 | (a ^ result) &gt;= 0); // if false, throw exception
return result;
}

// on overflow in case 1: a,b same sign, 2: a, b different sign, a and result same sign
public static long checkedSubtract(long a, long b) {
long result = a - b;
checkNoOverflow((a ^ b) &gt;= 0 | (a ^ result) &gt;= 0);
return result;
}

public static short checkedCast(long value) {
short result = (short) value;
checkArgument(result == value, "Out of range: %s", value);
return result;
}

Upcasting
https://www.securecoding.cert.org/confluence/display/java/NUM00-J.+Detect+or+prevent+integer+overflow
public static int multAccum(int oldAcc, int newVal, int scale)
                  throws ArithmeticException {
  final long res = intRangeCheck(
   ((long) oldAcc) + intRangeCheck((long) newVal * (long) scale)
  );
  return (int) res; // safe down-cast
}

RangesMatcher
public static final CharMatcher DIGIT = new RangesMatcher(
      "CharMatcher.DIGIT", ZEROES.toCharArray(), NINES.toCharArray());
public boolean matches(char c) {
int index = Arrays.binarySearch(rangeStarts, c);
if (index &gt;= 0) {
return true;
} else {
index = ~index - 1;
return index &gt;= 0 && c &lt;= rangeEnds[index];
}
}

Use bitset 
public static final CharMatcher JAVA_ISO_CONTROL =inRange('\u0000', '\u001f').or(inRange('\u007f', '\u009f'))
static CharMatcher inRange(final char startInclusive, final char endInclusive,
String description) {
return new FastMatcher(description) {
@Override public boolean matches(char c) {
return startInclusive &lt;= c && c &lt;= endInclusive;
}

@GwtIncompatible("java.util.BitSet")
@Override void setBits(BitSet table) {
table.set(startInclusive, endInclusive + 1);
}
};
}

Using Guava



https://www.techiedelight.com/convert-string-list-characters-java/

List<Character> chars = Lists.charactersOf(string);
List<Character> chars = Chars.asList(string.toCharArray());
public static List<Character> convert(String string) {
return new AbstractList<Character>() {

@Override
public Character get(int index) {
return string.charAt(index);
}

@Override
public int size() {
return string.length();
}
};
}
System.out.println(convert(string));

List<Character> chars = string.chars()  // IntStream
.mapToObj(e -> (char)e) // Stream<Character>
.collect(Collectors.toList());

https://github.com/google/guava/wiki/CachesExplained
乍看 checkArgument 與 checkState 感覺會有點像,是的!如果你只使用 assert 的話,基本上都是給個判斷條件,然後在不成立時產生錯誤。使用 checkArgument 與 checkState 的差別除了一個會丟出 IllegalArgumentException,一個是丟出 IllegalStateException 之外,最主要的是在語義差別,checkArgument 名稱表明這個方法是用於檢查引數,而 checkState 名稱表明,這個方法是用於檢查物件的狀態。

https://stackoverflow.com/questions/13532978/using-guava-cache-without-a-load-function
CacheBuilder.build() returns a non-loading cache. Just what you want. Just use
Cache<String, String> cache = CacheBuilder.newBuilder().build();
https://www.baeldung.com/guava-cache
    CacheLoader<String, String> loader;
    loader = new CacheLoader<String, String>() {
        @Override
        public String load(String key) {
            return key.toUpperCase();
        }
    };
    LoadingCache<String, String> cache;
    cache = CacheBuilder.newBuilder().maximumSize(3).build(loader);


Note: Many soft references may affect the system performance – it’s preferred to use maximumSize().

Now, let’s see how to handle cache null values. By default, Guava Cache will throw exceptions if you try to load a null value – as it doesn’t make any sense to cache a null.
But if null value means something in your code, then you can make good use of the Optional class as in the following example:
https://stackoverflow.com/questions/11709300/why-doesnt-google-guava-preconditionss-checkargument-return-a-value
The biggest single reason that checkNotNull returns its argument is so it can be used in constructors, like so:
public Foo(Bar bar) {
  this.bar = checkNotNull(bar);
}
But the main reason that checkArgument doesn't do something similar is that you'd have to pass the argument separately anyway, and it just doesn't seem worth it -- especially with more complicated precondition checks, which can sometimes be more readable on their own line. Just because something can be a one-liner doesn't mean that it should be, if it doesn't increase readability.
https://github.com/google/guava/wiki/OrderingExplained
natural()Uses the natural ordering on Comparable types.
usingToString()Compares objects by the lexicographical ordering of their string representations, as returned by toString().
Making a preexisting Comparator into an Ordering is as simple as using Ordering.from(Comparator).
But the more common way to create a custom Ordering is to skip the Comparator entirely in favor of extending the Ordering abstract class directly:
Ordering<String> byLengthOrdering = new Ordering<String>() {
  public int compare(String left, String right) {
    return Ints.compare(left.length(), right.length());
  }
};
MethodDescription
reverse()Returns the reverse ordering.
nullsFirst()Returns an Ordering that orders nulls before non-null elements, and otherwise behaves the same as the original Ordering. See also nullsLast()
compound(Comparator)Returns an Ordering which uses the specified Comparator to "break ties."
lexicographical()Returns an Ordering that orders iterables lexicographically by their elements.
onResultOf(Function)Returns an Ordering which orders values by applying the function to them and then comparing the results using the original Ordering.
https://www.baeldung.com/guava-ordering

    List<Integer> integers = Arrays.asList(3, 2, 1);

    integers.sort(Ordering.natural());

Ordering<Person> ordering = Ordering
  .natural()
  .nullsFirst()
  .onResultOf(new Function<Person, Comparable>() {
      @Override
      public Comparable apply(Person person) {
          return person.age;
      }
});
persons.sort(ordering);

https://openhome.cc/Gossip/CodeData/GuavaTutorial/Ordering.html
Collections.sort(names, 
        Ordering.natural().reverse().nullsFirst()
                .onResultOf(new Function<String, Integer>() {
                    @Override
                    public Integer apply(String p) {
                        return p == null ? null : p.length();
                    }
               })
);
Ordering 本身就是比較器,這看看它的類別定義就知道了:
Collections.sort(names, 
        Ordering.natural().reverse().nullsFirst()
            .onResultOf(p -> p == null ? null : p.length())
);
public abstract class Ordering<T> extends Object implements Comparator<T>
https://www.leveluplunch.com/java/tutorials/008-using-guava-fluent-ordering-comparator-part1/
    Collections.sort(numbers, Ordering.natural().reversed());

    Integer maxValue = Ordering.natural().max(numbers);

    Integer minValue = Ordering.natural().min(numbers);

Comparator<String> byLength = new Comparator<String>() {
    public int compare(String left, String right) {
        return Integer.compare(left.length(), right.length());
    }
};
    Comparator<String> reversedByLength = Ordering.from(byLength).reversed();
    Collections.sort(random, reversedByLength);



assertTrue(Ordering.from(reversedByLength).isOrdered(random));

Ordering by field
https://github.com/google/guava/wiki/CommonObjectUtilitiesExplained
ComparisonChain performs a "lazy" comparison: it only performs comparisons until it finds a nonzero result, after which it ignores further input.
   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();
   }
https://myshittycode.com/2013/12/28/java-performing-2-key-lookup-using-hashbasedtable/
HashBasedTable<String, String, String> hashBasedTable = HashBasedTable.create();
hashBasedTable.put("key1", "key2", "mike");

String value = hashBasedTable.get("key1", "key2"); // "mike"

https://stackoverflow.com/questions/31422443/best-practices-for-using-multi-level-hashmap-in-java
Alternatively, one could look into a Guava Table, as that does the same sort of thing, with a better interface to it (something like the one I have above).
Multi-level HashMaps are not necessarily bad, it depends on your algorithm. The bad thing is that it's more difficult to manage. Consider using interfaces (something like repository) for HasMap values, this may make your design cleaner. Other option is to use composite keys in a HashMap.
http://www.tothenew.com/blog/multikeymap-nested-maps-solution/
Apache

2
3
4
5
6
MultiKeyMap multiKeyMap=MultiKeyMap.decorate(new LinkedHahMap())
multiKeyMap.put("key1","key2","key3","value1") // Last parameter is value against defined keys.
multiKeyMap.put("key11","key22","key33","key44","value11")
multiKeyMap.put("key111","key222","key333","value111")
multiKeyMap.put("key1111","key2222","value1111")
This is how we create a map with multiple keys. Now let’s see how to fetch value out of multiKeyMap for one combination of keys.
PS :- One point to note is you have to provide combination of key in the same sequence that you provided while puting into map.
MultiKey which is again an another way to solve above use case.A MultiKey allows multiple map keys to be merged together

MultiKey multiKey=new MultiKey("key1","key2","key3")
MultikeyMap multiKeyMap=MultiKeyMap.decorator(new LinkedHashMap())
//Map map = new HashMap(); you can also use simple Map while using Multikey.
multiKeyMap.put(multiKey,"value1")
//To fetch value from map using multikey, we simply do as follows :-
multiKeyMap.get(multiKey)
https://jindongpu.wordpress.com/2016/08/23/google-guava-cache-example/
this.cache = CacheBuilder.newBuilder()
    .maximumSize(10)
    .expireAfterAccess(5, TimeUnit.SECONDS)
    .build(new CacheLoader<String, Record>() {

  @Override
  public Record load(String key) throws Exception {
    return getFromDatabase(key);
  }

});

cache.get(KEY2).data

http://stackoverflow.com/questions/12721735/how-to-receive-difference-of-maps-in-java
How about google guava?:
Maps.difference(map1,map2)
http://stackoverflow.com/questions/4283351/how-to-replace-special-characters-in-a-string
String alphaOnly = input.replaceAll("[^\\p{Alpha}]+","");
String alphaAndDigits = input.replaceAll("[^\\p{Alpha}\\p{Digit}]+","");
(All of these can be significantly improved by precompiling the regex pattern and storing it in a constant)
Or, with Guava:
private static final CharMatcher ALNUM =
  CharMatcher.inRange('a', 'z').or(CharMatcher.inRange('A', 'Z'))
  .or(CharMatcher.inRange('0', '9')).precomputed();
// ...
String alphaAndDigits = ALNUM.retainFrom(input);
https://github.com/google/guava/wiki/GraphsExplained
Graph<Integer> graph = GraphBuilder.directed().build();  // graph is empty
graph.putEdge(1, 2);  // this adds 1 and 2 as nodes of this graph, and puts
                      // an edge between them
if (graph.nodes().contains(1)) {  // evaluates to "true"
  ...
}
http://stackoverflow.com/questions/304268/getting-a-files-md5-checksum-in-java
Guava now provides a new, consistent hashing API that is much more user-friendly than the various hashing APIs provided in the JDK. See Hashing Explained. For a file, you can get the MD5 sum, CRC32 (with version 14.0+) or many other hashes easily:
HashCode md5 = Files.hash(file, Hashing.md5());
byte[] md5Bytes = md5.asBytes();
String md5Hex = md5.toString();

HashCode crc32 = Files.hash(file, Hashing.crc32());
int crc32Int = crc32.asInt();

// the Checksum API returns a long, but it's padded with 0s for 32-bit CRC
// this is the value you would get if using that API directly
long checksumResult = crc32.padToLong();
https://github.com/google/guava/wiki/HashingExplained
Once a Hasher has been given all its input, its hash() method can be used to retrieve a HashCode. (The behavior of hash() is unspecified if called more than once.) HashCodesupports equality testing and such, as well as asInt()asLong()asBytes() methods, and additionally, writeBytesTo(array, offset, maxLength), which writes the first maxLength bytes of the hash into the array.

Hasher hasher = hf.newHasher().putString("123", Charsets.UTF_8);
System.out.println(hasher.hash());

System.out.println(hasher.hash());


Exception in thread "main" java.lang.IllegalStateException: Cannot re-use a Hasher after calling hash() on it
at com.google.common.base.Preconditions.checkState(Preconditions.java:174)
at com.google.common.hash.MessageDigestHashFunction$MessageDigestHasher.checkNotDone(MessageDigestHashFunction.java:149)

at com.google.common.hash.MessageDigestHashFunction$MessageDigestHasher.hash(MessageDigestHashFunction.java:154)

BloomFilter<Person> friends = BloomFilter.create(personFunnel, 500, 0.01);
for(Person friend : friendsList) {
  friends.put(friend);
}
// much later
if (friends.mightContain(dude)) {
  // the probability that dude reached this place if he isn't a friend is 1%
  // we might, for example, start asynchronously loading things for dude while we do a more expensive exact check
}
https://plus.google.com/+googleguava/posts/hfBvW6xSt8y
2) If you’re hashing a String, don’t use String#getBytes. Instead, let us do the conversion to bytes for you.
  Hashing.md5().hashBytes(myString.getBytes(Charsets.UTF_8)); // Don’t do this.
  Hashing.md5().hashString(myString, Charsets.UTF_8); // Do this!
More importantly, never use the parameter-less version of String#getBytes because it silently uses the default Charset under the hood [2] (which is bad bad bad).

3) Instead of converting your HashCode instance to a primitive (like an int or long), instead use HashCode as a first class object! It’s simple, immutable, thread-safe, and suitable for adding to collections or exposing in APIs.
  int hash = Hashing.md5().hashBytes(bytez).asInt(); // Don’t do this.
  HashCode hash = Hashing.md5().hashBytes(bytez); // Do this!
In this example, we’re also losing bits of our hash code by collaring the 128-bit MD5 HashCode instance down to only 32-bits. The HashCode instance retains the full hash of the data.


https://www.baeldung.com/guava-joiner-and-splitter-tutorial
    String result = Joiner.on(",").join(names);
    List<String> result = Splitter.on("-").trimResults()
                                          .splitToList(input);
    String result = Joiner.on(",").useForNull("nameless").join(names);
    String result = Joiner.on(" , ").withKeyValueSeparator(" = ")
                                    .join(salary);
    List<String> result = Splitter.on("-").trimResults()
                                          .splitToList(input);
    Map<String, String> result = Splitter.on(",")
                                         .withKeyValueSeparator("=")
                                         .split(input);
8. Split String with multiple separators
    String input = "apple.banana,,orange,,.";
    List<String> result = Splitter.onPattern("[.,]")
                                  .omitEmptyStrings()
                                  .splitToList(input);
    List<String> result = Splitter.fixedLength(3).splitToList(input);
    List<String> result = Splitter.on(",")
                                  .limit(4)
                                  .splitToList(input);


http://www.diguage.com/archives/143.html

Map 相关的 Joiner 和 Splitter

第一个问题:D瓜哥需要从 URL 中获取相关请求的参数,并且将其转化成 Key-Value 形式放到 Map对象,方便后续操作。
URL 中,参数的格式大家应该都了解:http://www.diguage.com?userName=diguage&sex=fale。以 ? 分割后,后面的就是参数。如果自己手动写,还有一个一个分割,实在是懒得动手了。其实 Guava中内置了非常方便的方法来解决这个问题。代码如下:
int paramSeparater = url.indexOf("?");
String host = url.substring(0, paramSeparater);
String params = fromUrl.substring(paramSeparater + 1);
Map<String, String> paramMap = Maps.newHashMap();
Map<String, String> paramMap = Splitter.on("&").withKeyValueSeparator("=").split(params);
反过来,我们可能还需有将 Map 对象转化成 URL 的参数,来拼接出一个带参数的 URL。Guava 中也有非常方便的相关方法。代码如下:
Map<String, String> paramMap = Maps.newHashMap();
paramMap.put("userName", "diguage");
paramMap.put("webSite", "http://www.diguage.com/");
String url = url + "?" + Joiner.on("&").withKeyValueSeparator("=").join(paramMap);

我们的项目中,使用了 Spring JdbcTemplate,并基于这个这个东东写了一个 BaseDao,再结合注解,就可以获取表名和字段名。为了统一,规定将数据表以及字段的多个字母以下划线分割。大家都知道,Java 中类名以及属性名,都是驼峰命名法。那么就需要一个转化。 Guava 也提供了很方便的方法。代码如下:
1String tableName = CaseFormat.UPPER_CAMEL.to(CaseFormat.LOWER_UNDERSCORE, clazz.getSimpleName());
在上述代码中, CaseFormat 中设定了几个常用的格式:
  • LOWER_CAMEL – 以小写字母开头的驼峰命名规则。例如: lowerCamel。这个规则符合表示 Java 属性以及 Java 方法的命名规则。
  • LOWER_HYPHEN – 将单词的小写形式以连接符( - )连接的。例如: lower-hyphen
  • LOWER_UNDERSCORE – 将单词的小写形式以连接符( _ )连接的。例如: lower_underscore
  • UPPER_CAMEL – 以大写字母开头的驼峰命名规则。例如: UpperCamel。这个规则符合表示 Java 或 C++ 类名的命名规则。
  • UPPER_UNDERSCORE – 将单词的大写形式以连接符( _ )连接的。例如: UPPER_UNDERSCORE。这个规则符合表示 Java 或 C++ 常量的命名规则。
组合使用这几个规则,可以方便地进行字符串形式的转换。例如,将上面的表名转化成类名:
1String className = CaseFormat.LOWER_UNDERSCORE.to(CaseFormat.UPPER_CAMEL, tableName);
最后一个问题:需要将一个当前 URL 传递到下一个请求中,方便做跳转回来。作为参数传递,肯定需要对 URL 编码,否则作为参数的 URL 的参数就可能丢失了。 Guava 中通过也可以很好的支持:
1String currentUrl = UrlEscapers.urlFormParameterEscaper().escape("http://www.diguage.com?userName=diguage");
https://github.com/google/guava/issues/556
compare(a, b, Ordering.natural().nullsFirst())
return ComparisonChain.start() .compare(user.getUpdateDate(), other.getUser().getUpdateDate(), Ordering.natural().nullsLast()) .result();

https://google.github.io/guava/releases/19.0/api/docs/com/google/common/collect/ComparisonChain.html
   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();
   }

http://stackoverflow.com/questions/23615451/how-does-lists-newarraylist-of-guava-library-work
Because the compiler can infer the type from the variable declaration.
Example:
List<String> list = Lists.newArrayList(),
the compiler will understand that the type of the collection (the type of E) will be <String>, since you expect to get a List of String.
It was useful to avoid rewriting entire <> arguments, but with Java7 and diamond operator you can avoid it using
List<String> list = new ArrayList<>();
=
http://stackoverflow.com/questions/6802483/how-to-directly-initialize-a-hashmap-in-a-literal-way
Map<String, Integer> left = ImmutableMap.of("a", 1, "b", 2, "c", 3);
This works for up to 5 key/value pairs, otherwise you can use its builder:
Map<String, String> test = ImmutableMap.<String, String>builder()
    .put("k1", "v1")
    .put("k2", "v2")
    ...
    .build();
  • note that Guava's ImmutableMap implementation differs from Java's HashMap implementation (most notably it is immutable and does not permit null keys/values)
http://bethecoder.com/applications/tutorials/tools-and-libs/google-guava/collections/map-values-transform.html

    Map<String, String> transMap = 
      Maps.transformValues(immutableMap, new Function<Integer, String>() {

        @Override
        public String apply(Integer input) {
          return "BTC-" + input; //new value in transformed map
        }
    });
Why Guava does not provide a way to transform map keys


checkArgument(count > 0, "must be positive: %s", count);
Google Guava EventBus - an Easy and Elegant Way for Your Publisher - Subscriber Use Cases
    EventBus eventBus = new EventBus("test");
    EventListener listener = new EventListener();

    eventBus.register(listener);

    // when
    eventBus.post(new OurTestEvent(200));

    @Subscribe
    public void listen(OurTestEvent event) {
        lastMessage = event.getMessage();
    }

Limiting the size of InputStreams
https://stonelion.gitbooks.io/guava_ch/content/working_with_files/limiting_the_size_of_inputstreams.html
ByteSteams.limit方法使用InputStream和一个long值作为参数,并返回一个包装了的InputStream,这个InputStream只会读取与给定long值相等的byte数。

http://stackoverflow.com/questions/15445504/copy-inputstream-abort-operation-if-size-exceeds-limit
public class LimitedSizeInputStream extends InputStream {

    private final InputStream original;
    private final long maxSize;
    private long total;

    public LimitedSizeInputStream(InputStream original, long maxSize) {
        this.original = original;
        this.maxSize = maxSize;
    }

    @Override
    public int read() throws IOException {
        int i = original.read();
        if (i>=0) incrementCounter(1);
        return i;
    }

    @Override
    public int read(byte b[]) throws IOException {
        return read(b, 0, b.length);
    }

    @Override
    public int read(byte b[], int off, int len) throws IOException {
        int i = original.read(b, off, len);
        if (i>=0) incrementCounter(i);
        return i;
    }

    private void incrementCounter(int size) throws IOException {
        total += size;
        if (total>maxSize) throw new IOException("InputStream exceeded maximum size in bytes.");
    }

}
The main difference of the implementation above with BoundedInputStream is that BoundedInputStream does not throw an exception when the limit is exceeded (it just closes the stream)

Hashing a file
HashCode hashCode = Files.hash(file, Hashing.md5());

firstNonNull方法使用两个参数并且返回非空的那个参数。

String value = Objects.firstNonNull(someString,"default value");
firstNonNull 方法可以在当你并不确定对象是否是空的情况下,用于作为一种提供默认值的方式。 需要注意的是,如果两个参数都为空,那么会抛出NullPointerException错误。

新版本中Objects.firstNonNull已经是Deprecated的了,使用MoreObjects.firstNonNull(T first,T second)替换。

用于保证调用Closer.close方法时,所有注册的Closeable对象都正确的关闭。
Closer closer = Closer.create();
try{
closer.register(reader);
} catch (Throwable t) {
    throw closer.rethrow(t);
} finally {
    closer.close();
}
Using Preconditions
https://code.google.com/p/guava-libraries/wiki/PreconditionsExplained

https://code.google.com/p/guava-libraries/wiki/CommonObjectUtilitiesExplained
equals, hashCode
Use ComparisonChain
ComparisonChain.start().compare(this.anInt, that.anInt).compare(this.anEnum, that.anEnum, Ordering.natural().nullsLast()).result();
Objects.toStringHelper("MyObject").add("x", 1).toString();

String: Joiner
Joiner joiner = Joiner.on("; ").skipNulls();
joiner.join("Harry", null, "Ron", "Hermione");
final Joiner.MapJoiner mapJoiner = Joiner.on('&').withKeyValueSeparator("=");
final ImmutableMap<String, String> values = ImmutableMap.of("name", "mrhaki", "worksAt", "JDriven");
assert mapJoiner.join(values).equals("name=mrhaki&worksAt=JDriven");

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

CharMatcher
String noControl = CharMatcher.JAVA_ISO_CONTROL.removeFrom(string); // remove control characters
String spaced = CharMatcher.WHITESPACE.trimAndCollapseFrom(string, ' ');
bytes = string.getBytes(Charsets.UTF_8);

Escapers
HtmlEscapers.htmlEscaper().escape(str)
XmlEscapers.xmlContentEscaper()/xmlAttributeEscaper().escape(str)
UrlEscapers.urlFormParameterEscaper()/urlFragmentEscaper()/urlPathSegmentEscaper()/urlFormParameterEscaper().

Net
com.google.common.net.InetAddresses.isInetAddress(String)

Collections

Google Guava RateLimiter
@ThreadSafe
javax.annotation.concurrent.ThreadSafe

* TODO(cpovirk): make SleepingStopwatch the last parameter throughout the class so that the
* overloads follow the usual convention: Foo(int), Foo(int, SleepingStopwatch)

@WebFilter(urlPatterns=Array("/*"))
class RateLimiterFilter extends Filter {
    val limiter = RateLimiter.create(100)
    def init(filterConfig: FilterConfig) {}
    def doFilter(request: ServletRequest, response: ServletResponse, chain: FilterChain) {
        if(limiter.tryAcquire()) {
            chain.doFilter(request, response)
        } else {
            response.asInstanceOf[HttpServletResponse].sendError(SC_TOO_MANY_REQUESTS)
        }
    }
    def destroy() {}
}

Labels

Review (572) System Design (334) System Design - Review (198) Java (189) Coding (75) Interview-System Design (65) Interview (63) Book Notes (59) Coding - Review (59) to-do (45) Linux (43) Knowledge (39) Interview-Java (35) Knowledge - Review (32) Database (31) Design Patterns (31) Big Data (29) Product Architecture (28) MultiThread (27) Soft Skills (27) Concurrency (26) Cracking Code Interview (26) Miscs (25) Distributed (24) OOD Design (24) Google (23) Career (22) Interview - Review (21) Java - Code (21) Operating System (21) Interview Q&A (20) System Design - Practice (20) Tips (19) Algorithm (17) Company - Facebook (17) Security (17) How to Ace Interview (16) Brain Teaser (14) Linux - Shell (14) Redis (14) Testing (14) Tools (14) Code Quality (13) Search (13) Spark (13) Spring (13) Company - LinkedIn (12) How to (12) Interview-Database (12) Interview-Operating System (12) Solr (12) Architecture Principles (11) Resource (10) Amazon (9) Cache (9) Git (9) Interview - MultiThread (9) Scalability (9) Trouble Shooting (9) Web Dev (9) Architecture Model (8) Better Programmer (8) Cassandra (8) Company - Uber (8) Java67 (8) Math (8) OO Design principles (8) SOLID (8) Design (7) Interview Corner (7) JVM (7) Java Basics (7) Kafka (7) Mac (7) Machine Learning (7) NoSQL (7) C++ (6) Chrome (6) File System (6) Highscalability (6) How to Better (6) Network (6) Restful (6) CareerCup (5) Code Review (5) Hash (5) How to Interview (5) JDK Source Code (5) JavaScript (5) Leetcode (5) Must Known (5) Python (5)

Popular Posts