Google Guava 库用法整理<转>

参考: 
http://codemunchies.com/2009/10/beautiful-code-with-google-collections-guava-and-static-imports-part-1/(2,3,4) 
http://blog.publicobject.com

更多用法参考http://ajoo.iteye.com/category/119082

附 guava中文api地址http://ifeve.com/google-guava/

以前这么用:

  1. Map<String, Map<Long, List<String>>> map = new HashMap<String, Map<Long,List<String>>>();

现在这么用(JDK7将实现该功能):

  1. Map<String, Map<Long, List<String>>> map = Maps.newHashMap();

针对不可变集合: 
以前这么用:

  1. List<String> list = new ArrayList<String>();
  2. list.add("a");
  3. list.add("b");
  4. list.add("c");
  5. list.add("d");

现在Guava这么用:

  1. ImmutableList<String> of = ImmutableList.of("a", "b", "c", "d");
  2. ImmutableMap<String,String> map = ImmutableMap.of("key1", "value1", "key2", "value2");

文本文件读取现在Guava这么用

  1. File file = new File(getClass().getResource("/test.txt").getFile());
  2. List<String> lines = null;
  3. try {
  4. lines = Files.readLines(file, Charsets.UTF_8);
  5. } catch (IOException e) {
  6. e.printStackTrace();
  7. }

基本类型比较, 现在Guava这么用:

  1. int compare = Ints.compare(a, b);

Guava中CharMatcher的用法:

  1. assertEquals("89983", CharMatcher.DIGIT.retainFrom("some text 89983 and more"))
  2. assertEquals("some text  and more", CharMatcher.DIGIT.removeFrom("some text 89983 and more"))

Guava中Joiner的用法:

  1. int[] numbers = { 1, 2, 3, 4, 5 };
  2. String numbersAsString = Joiner.on(";").join(Ints.asList(numbers));

另一种写法:

  1. String numbersAsStringDirectly = Ints.join(";", numbers);

Guava中Splitter的用法:

  1. Iterable split = Splitter.on(",").split(numbsAsString);

对于这样的字符串进行切分:

  1. String testString = "foo , what,,,more,";
  2. Iterable<String> split = Splitter.on(",").omitEmptyStrings().trimResults().split(testString);

Ints中一些用法:

  1. int[] array = { 1, 2, 3, 4, 5 };
  2. int a = 4;
  3. boolean contains = Ints.contains(array, a);
  4. int indexOf = Ints.indexOf(array, a);
  5. int max = Ints.max(array);
  6. int min = Ints.min(array);
  7. int[] concat = Ints.concat(array, array2);

集合 
set的交集, 并集, 差集的用法(http://publicobject.com/2008/08/coding-in-small-with-google-collections.html)

  1. HashSet setA = newHashSet(1, 2, 3, 4, 5);
  2. HashSet setB = newHashSet(4, 5, 6, 7, 8);
  3. SetView union = Sets.union(setA, setB);
  4. System.out.println("union:");
  5. for (Integer integer : union)
  6. System.out.println(integer);
  7. SetView difference = Sets.difference(setA, setB);
  8. System.out.println("difference:");
  9. for (Integer integer : difference)
  10. System.out.println(integer);
  11. SetView intersection = Sets.intersection(setA, setB);
  12. System.out.println("intersection:");
  13. for (Integer integer : intersection)
  14. System.out.println(integer);

针对Map的用法:

  1. MapDifference differenceMap = Maps.difference(mapA, mapB);
  2. differenceMap.areEqual();
  3. Map entriesDiffering = differenceMap.entriesDiffering();
  4. Map entriesOnlyOnLeft = differenceMap.entriesOnlyOnLeft();
  5. Map entriesOnlyOnRight = differenceMap.entriesOnlyOnRight();
  6. Map entriesInCommon = differenceMap.entriesInCommon();

验证与条件检查 
原来的写法:

  1. if (count <= 0) {
  2. throw new IllegalArgumentException("must be positive: " + count);
  3. }

Guava的写法(Jakarta Commons中有类似的方法):

  1. Preconditions.checkArgument(count > 0, "must be positive: %s", count);

一个更酷的用法:

  1. public PostExample(final String title, final Date date, final String author) {
  2. this.title = checkNotNull(title);
  3. this.date = checkNotNull(date);
  4. this.author = checkNotNull(author);
  5. }

如果一个key对应多个value的Map, 你会怎么处理? 如果还在使用Map<K, List<V>>的话, 你就out了 
使用MultiMap吧:

  1. Multimap<Person, BlogPost> multimap = ArrayListMultimap.create();

Multimap的另一个使用场景: 
比如有一个文章数据的map:

  1. List<Map<String, String>> listOfMaps = mapOf("type", "blog", "id", "292", "author", "john");

如果要按照type分组生成一个List

  1. Multimap<String, Map<String, String>> partitionedMap = Multimaps.index(
  2. listOfMaps,
  3. new Function<Map<String, String>, String>() {
  4. public String apply(final Map<String, String> from) {
  5. return from.get("type");
  6. }
  7. });

针对集合中只有一个元素的情况: 
Iterables.getOnlyElement(); 
这个主要是用来替换Set.iterator.next()或 List.get(0), 而且在测试中使用非常方便, 如果出现0个或者2+则直接抛出异常

比较的最大最小值: 
Comparators.max 
Comparators.min

equals和hashcode的用法:

  1. public boolean equals(Object o) {
  2. if (o instanceof Order) {
  3. Order that = (Order)o;
  4. return Objects.equal(address, that.address)
  5. && Objects.equal(targetArrivalDate, that.targetArrivalDate)
  6. && Objects.equal(lineItems, that.lineItems);
  7. } else {
  8. return false;
  9. }
  10. }
  11. public int hashCode() {
  12. return Objects.hashCode(address, targetArrivalDate, lineItems);
  13. }

ImmutableList.copyOf的用法: 
以前这么用:

  1. public Directions(Address from, Address to, List<Step> steps) {
  2. this.from = from;
  3. this.to = to;
  4. this.steps = Collections.unmodifiableList(new ArrayList<Step>(steps));
  5. }

现在这么用:

  1. public Directions(Address from, Address to, List<Step> steps) {
  2. this.from = from;
  3. this.to = to;
  4. this.steps = ImmutableList.of(steps);
  5. }

Iterables.concat()的用法: 
以前这么用:

  1. public boolean orderContains(Product product) {
  2. List<LineItem> allLineItems = new ArrayList<LineItem>();
  3. allLineItems.addAll(getPurchasedItems());
  4. allLineItems.addAll(getFreeItems());
  5. for (LineItem lineItem : allLineItems) {
  6. if (lineItem.getProduct() == product) {
  7. return true;
  8. }
  9. }
  10. return false;
  11. }

现在这么用:

  1. public boolean orderContains(Product product) {
  2. for (LineItem lineItem : Iterables.concat(getPurchasedItems(), getFreeItems())) {
  3. if (lineItem.getProduct() == product) {
  4. return true;
  5. }
  6. }
  7. return false;
  8. }

Constraints.constrainedList: 给List操作注入约束逻辑, 比如添加不合法元素直接报错. 
以前这么写:

  1. private final List<LineItem> purchases = new ArrayList<LineItem>();
  2. /**
  3. * Don't modify this! Instead, call {@link #addPurchase(LineItem)} to add
  4. * new purchases to this order.
  5. */
  6. public List<LineItem> getPurchases() {
  7. return Collections.unmodifiableList(purchases);
  8. }
  9. public void addPurchase(LineItem purchase) {
  10. Preconditions.checkState(catalog.isOffered(getAddress(), purchase.getProduct()));
  11. Preconditions.checkState(purchase.getCharge().getUnits() > 0);
  12. purchases.add(purchase);
  13. }
  14. 这么写:
  15. private final List<LineItem> purchases = Constraints.constrainedList(
  16. new ArrayList<LineItem>(),
  17. new Constraint<LineItem>() {
  18. public void checkElement(LineItem element) {
  19. Preconditions.checkState(catalog.isOffered(getAddress(), element.getProduct()));
  20. Preconditions.checkState(element.getCharge().getUnits() > 0);
  21. }
  22. });
  23. /**
  24. * Returns the modifiable list of purchases in this order.
  25. */
  26. public List<LineItem> getPurchases() {
  27. return purchases;
  28. }

不允许插入空值的Set(Constraints的用法):

  1. Set<String> set = Sets.newHashSet();
  2. Set<String> constrainedSet = Constraints.constrainedSet(set, Constraints.notNull());
  3. constrainedSet.add("A");
  4. constrainedSet.add(null); // NullPointerException here

Multimap的用法(允许多值的map): 
以前这么写:

  1. Map<Salesperson, List<Sale>> map = new Hashmap<SalesPerson, List<Sale>>();
  2. public void makeSale(Salesperson salesPerson, Sale sale) {
  3. List<Sale> sales = map.get(salesPerson);
  4. if (sales == null) {
  5. sales = new ArrayList<Sale>();
  6. map.put(salesPerson, sales);
  7. }
  8. sales.add(sale);
  9. }

现在这么写:

  1. Multimap<Salesperson, Sale> multimap
  2. = new ArrayListMultimap<Salesperson,Sale>();
  3. public void makeSale(Salesperson salesPerson, Sale sale) {
  4. multimap.put(salesperson, sale);
  5. }

以前这么写:

  1. public Sale getBiggestSale() {
  2. Sale biggestSale = null;
  3. for (List<Sale> sales : map.values()) {
  4. Sale biggestSaleForSalesman
  5. = Collections.max(sales, SALE_COST_COMPARATOR);
  6. if (biggestSale == null
  7. || biggestSaleForSalesman.getCharge() > biggestSale().getCharge()) {
  8. biggestSale = biggestSaleForSalesman;
  9. }
  10. }
  11. return biggestSale;
  12. }

现在这么写(需要将map转换成multimap):

  1. public Sale getBiggestSale() {
  2. return Collections.max(multimap.values(), SALE_COST_COMPARATOR);
  3. }

Joiner的用法: 
以前这样写:

  1. public class ShoppingList {
  2. private List<Item> items = ...;
  3. ...
  4. public String toString() {
  5. StringBuilder stringBuilder = new StringBuilder();
  6. for (Iterator<Item> s = items.iterator(); s.hasNext(); ) {
  7. stringBuilder.append(s.next());
  8. if (s.hasNext()) {
  9. stringBuilder.append(" and ");
  10. }
  11. }
  12. return stringBuilder.toString();
  13. }
  14. }

现在这样写:

  1. public class ShoppingList {
  2. private List<Item> items = ...;
  3. ...
  4. public String toString() {
  5. return Join.join(" and ", items);
  6. }
  7. }

Comparators.fromFunction的用法: 
以前这样写:

  1. public Comparator<Product> createRetailPriceComparator(
  2. final CurrencyConverter currencyConverter) {
  3. return new Comparator<Product>() {
  4. public int compare(Product a, Product b) {
  5. return getRetailPriceInUsd(a).compareTo(getRetailPriceInUsd(b));
  6. }
  7. public Money getRetailPriceInUsd(Product product) {
  8. Money retailPrice = product.getRetailPrice();
  9. return retailPrice.getCurrency() == CurrencyCode.USD
  10. ? retailPrice
  11. : currencyConverter.convert(retailPrice, CurrencyCode.USD);
  12. }
  13. };
  14. }

现在这样写(感觉也没省多少):

  1. public Comparator<Product> createRetailPriceComparator(
  2. final CurrencyConverter currencyConverter) {
  3. return Comparators.fromFunction(new Function<Product,Money>() {
  4. /** returns the retail price in USD */
  5. public Money apply(Product product) {
  6. Money retailPrice = product.getRetailPrice();
  7. return retailPrice.getCurrency() == CurrencyCode.USD
  8. ? retailPrice
  9. : currencyConverter.convert(retailPrice, CurrencyCode.USD);
  10. }
  11. });
  12. }

BiMap(双向map)的用法: 
以前的用法:

  1. private static final Map<Integer, String> NUMBER_TO_NAME;
  2. private static final Map<String, Integer> NAME_TO_NUMBER;
  3. static {
  4. NUMBER_TO_NAME = Maps.newHashMap();
  5. NUMBER_TO_NAME.put(1, "Hydrogen");
  6. NUMBER_TO_NAME.put(2, "Helium");
  7. NUMBER_TO_NAME.put(3, "Lithium");
  8. /* reverse the map programatically so the actual mapping is not repeated */
  9. NAME_TO_NUMBER = Maps.newHashMap();
  10. for (Integer number : NUMBER_TO_NAME.keySet()) {
  11. NAME_TO_NUMBER.put(NUMBER_TO_NAME.get(number), number);
  12. }
  13. }
  14. public static int getElementNumber(String elementName) {
  15. return NUMBER_TO_NAME.get(elementName);
  16. }
  17. public static string getElementName(int elementNumber) {
  18. return NAME_TO_NUMBER.get(elementNumber);
  19. }

现在的用法:

  1. private static final BiMap<Integer,String> NUMBER_TO_NAME_BIMAP;
  2. static {
  3. NUMBER_TO_NAME_BIMAP = Maps.newHashBiMap();
  4. NUMBER_TO_NAME_BIMAP.put(1, "Hydrogen");
  5. NUMBER_TO_NAME_BIMAP.put(2, "Helium");
  6. NUMBER_TO_NAME_BIMAP.put(3, "Lithium");
  7. }
  8. public static int getElementNumber(String elementName) {
  9. return NUMBER_TO_NAME_BIMAP.inverse().get(elementName);
  10. }
  11. public static string getElementName(int elementNumber) {
  12. return NUMBER_TO_NAME_BIMAP.get(elementNumber);
  13. }

换一种写法:

  1. private static final BiMap<Integer,String> NUMBER_TO_NAME_BIMAP
  2. = new ImmutableBiMapBuilder<Integer,String>()
  3. .put(1, "Hydrogen")
  4. .put(2, "Helium")
  5. .put(3, "Lithium")
  6. .getBiMap();

关于Strings的一些用法(http://blog.ralscha.ch/?p=888):

  1. assertEquals("test", Strings.emptyToNull("test"));
  2. assertEquals(" ", Strings.emptyToNull(" "));
  3. assertNull(Strings.emptyToNull(""));
  4. assertNull(Strings.emptyToNull(null));
  5. assertFalse(Strings.isNullOrEmpty("test"));
  6. assertFalse(Strings.isNullOrEmpty(" "));
  7. assertTrue(Strings.isNullOrEmpty(""));
  8. assertTrue(Strings.isNullOrEmpty(null));
  9. assertEquals("test", Strings.nullToEmpty("test"));
  10. assertEquals(" ", Strings.nullToEmpty(" "));
  11. assertEquals("", Strings.nullToEmpty(""));
  12. assertEquals("", Strings.nullToEmpty(null));
  13. assertEquals("Ralph_____", Strings.padEnd("Ralph", 10, '_'));
  14. assertEquals("Bob_______", Strings.padEnd("Bob", 10, '_'));
  15. assertEquals("_____Ralph", Strings.padStart("Ralph", 10, '_'));
  16. assertEquals("_______Bob", Strings.padStart("Bob", 10, '_'));
  17. assertEquals("xyxyxyxyxy", Strings.repeat("xy", 5));

Throwables的用法(将检查异常转换成未检查异常):

  1. package com.ociweb.jnb.apr2010;
  2. import com.google.common.base.Throwables;
  3. import java.io.InputStream;
  4. import java.net.URL;
  5. public class ExerciseThrowables {
  6. public static void main(String[] args) {
  7. try {
  8. URL url = new URL("http://ociweb.com");
  9. final InputStream in = url.openStream();
  10. // read from the input stream
  11. in.close();
  12. } catch (Throwable t) {
  13. throw Throwables.propagate(t);
  14. }
  15. }
  16. }

Multimap用法整理(http://jnb.ociweb.com/jnb/jnbApr2008.html): 
用来统计多值出现的频率:

  1. Multimap<Integer, String> siblings = Multimaps.newHashMultimap();
  2. siblings.put(0, "Kenneth");
  3. siblings.put(1, "Joe");
  4. siblings.put(2, "John");
  5. siblings.put(3, "Jerry");
  6. siblings.put(3, "Jay");
  7. siblings.put(5, "Janet");
  8. for (int i = 0; i < 6; i++) {
  9. int freq = siblings.get(i).size();
  10. System.out.printf("%d siblings frequency %d\n", i, freq);
  11. }

输出结果:

引用
        0 siblings frequency 1 
        1 siblings frequency 1 
        2 siblings frequency 1 
        3 siblings frequency 2 
        4 siblings frequency 0 
        5 siblings frequency 1

Functions(闭包功能)

  1. Function<String, Integer> strlen = new Function<String, Integer>() {
  2. public Integer apply(String from) {
  3. Preconditions.checkNotNull(from);
  4. return from.length();
  5. }
  6. };
  7. List<String> from = Lists.newArrayList("abc", "defg", "hijkl");
  8. List<Integer> to = Lists.transform(from, strlen);
  9. for (int i = 0; i < from.size(); i++) {
  10. System.out.printf("%s has length %d\n", from.get(i), to.get(i));
  11. }

不过这种转换是在访问元素的时候才进行, 下面的例子可以说明:

    1. Function<String, Boolean> isPalindrome = new Function<String, Boolean>() {
    2. public Boolean apply(String from) {
    3. Preconditions.checkNotNull(from);
    4. return new StringBuilder(from).reverse().toString().equals(from);
    5. }
    6. };
    7. List<String> from = Lists.newArrayList("rotor", "radar", "hannah", "level", "botox");
    8. List<Boolean> to = Lists.transform(from, isPalindrome);
    9. for (int i = 0; i < from.size(); i++) {
    10. System.out.printf("%s is%sa palindrome\n", from.get(i), to.get(i) ? " " : " NOT ");
    11. }
    12. // changes in the "from" list are reflected in the "to" list
    13. System.out.printf("\nnow replace hannah with megan...\n\n");
    14. from.set(2, "megan");
    15. for (int i = 0; i < from.size(); i++) {
    16. System.out.printf("%s is%sa palindrome\n", from.get(i), to.get(i) ? " " : " NOT ");
    17. }

转自  http://macrochen.iteye.com/blog/737058

上一篇:Java高级特性 第1节 集合框架和泛型


下一篇:linq用法整理