Google Guava 庫用法整理

ptjs 12年前發布 | 2K 次閱讀 ChromeSnifferPlus

參考:
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

以前這么用:

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

現在這么用(JDK7將實現該功能):

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


針對不可變集合:
以前這么用:

List<String> list = new ArrayList<String>();
list.add("a");
list.add("b");
list.add("c");
list.add("d");

現在Guava這么用:

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


文本文件讀取現在Guava這么用

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


基本類型比較, 現在Guava這么用:

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


Guava中CharMatcher的用法:

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


Guava中Joiner的用法:

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

另一種寫法:

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


Guava中Splitter的用法:

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

對于這樣的字符串進行切分:

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


Ints中一些用法:

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


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

HashSet setA = newHashSet(1, 2, 3, 4, 5);
HashSet setB = newHashSet(4, 5, 6, 7, 8);

SetView union = Sets.union(setA, setB); System.out.println("union:"); for (Integer integer : union) System.out.println(integer);

SetView difference = Sets.difference(setA, setB); System.out.println("difference:"); for (Integer integer : difference) System.out.println(integer);

SetView intersection = Sets.intersection(setA, setB); System.out.println("intersection:"); for (Integer integer : intersection) System.out.println(integer);</pre>

針對Map的用法:

MapDifference differenceMap = Maps.difference(mapA, mapB);

differenceMap.areEqual(); Map entriesDiffering = differenceMap.entriesDiffering(); Map entriesOnlyOnLeft = differenceMap.entriesOnlyOnLeft(); Map entriesOnlyOnRight = differenceMap.entriesOnlyOnRight(); Map entriesInCommon = differenceMap.entriesInCommon();</pre>

驗證與條件檢查
原來的寫法:

if (count <= 0) {                                                                                         
    throw new IllegalArgumentException("must be positive: " + count);       
}  
    
           
Guava的寫法(Jakarta Commons中有類似的方法):

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


一個更酷的用法:

public PostExample(final String title, final Date date, final String author) {
    this.title = checkNotNull(title);
    this.date = checkNotNull(date);
    this.author = checkNotNull(author);
}


如果一個key對應多個value的Map, 你會怎么處理? 如果還在使用Map<K, List<V>>的話, 你就out了
使用MultiMap吧:

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


Multimap的另一個使用場景:
比如有一個文章數據的map:

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

如果要按照type分組生成一個List

Multimap<String, Map<String, String>> partitionedMap = Multimaps.index(   
                listOfMaps,                                                                                       
                new Function<Map<String, String>, String>() {                                 
                    public String apply(final Map<String, String> from) {                    
                        return from.get("type");                                                             
                    }                                                                                                   
                }); 
                                                                                                    
針對集合中只有一個元素的情況:
Iterables.getOnlyElement();
這個主要是用來替換Set.iterator.next()或 List.get(0), 而且在測試中使用非常方便, 如果出現0個或者2+則直接拋出異常

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

equals和hashcode的用法:

  public boolean equals(Object o) {
    if (o instanceof Order) {
      Order that = (Order)o;

  return Objects.equal(address, that.address)
      && Objects.equal(targetArrivalDate, that.targetArrivalDate)
      && Objects.equal(lineItems, that.lineItems);
} else {
  return false;
}

}

public int hashCode() { return Objects.hashCode(address, targetArrivalDate, lineItems); }</pre>

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

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

現在這么用:

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


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

  public boolean orderContains(Product product) {
    List<LineItem> allLineItems = new ArrayList<LineItem>();
    allLineItems.addAll(getPurchasedItems());
    allLineItems.addAll(getFreeItems());

for (LineItem lineItem : allLineItems) {
  if (lineItem.getProduct() == product) {
    return true;
  }
}

return false;

}</pre>
現在這么用:

  public boolean orderContains(Product product) {
    for (LineItem lineItem : Iterables.concat(getPurchasedItems(), getFreeItems())) {
      if (lineItem.getProduct() == product) {
        return true;
      }
    }

return false;

}</pre>

Constraints.constrainedList: 給List操作注入約束邏輯, 比如添加不合法元素直接報錯.
以前這么寫:

  private final List<LineItem> purchases = new ArrayList<LineItem>();

/**

  • Don't modify this! Instead, call {@link #addPurchase(LineItem)} to add
  • new purchases to this order. */ public List<LineItem> getPurchases() { return Collections.unmodifiableList(purchases); }

    public void addPurchase(LineItem purchase) { Preconditions.checkState(catalog.isOffered(getAddress(), purchase.getProduct())); Preconditions.checkState(purchase.getCharge().getUnits() > 0); purchases.add(purchase); } 現在這么寫: private final List<LineItem> purchases = Constraints.constrainedList( new ArrayList<LineItem>(), new Constraint<LineItem>() { public void checkElement(LineItem element) {

     Preconditions.checkState(catalog.isOffered(getAddress(), element.getProduct()));
     Preconditions.checkState(element.getCharge().getUnits() > 0);
    

    } });

    /**

  • Returns the modifiable list of purchases in this order. */ public List<LineItem> getPurchases() { return purchases; }</pre>

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

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


    Multimap的用法(允許多值的map):
    以前這么寫:
      Map<Salesperson, List<Sale>> map = new Hashmap<SalesPerson, List<Sale>>();

    public void makeSale(Salesperson salesPerson, Sale sale) { List<Sale> sales = map.get(salesPerson); if (sales == null) { sales = new ArrayList<Sale>(); map.put(salesPerson, sales); } sales.add(sale); }</pre>
    現在這么寫:

      Multimap<Salesperson, Sale> multimap 
     = new ArrayListMultimap<Salesperson,Sale>();

    public void makeSale(Salesperson salesPerson, Sale sale) { multimap.put(salesperson, sale); }</pre>
    以前這么寫:

      public Sale getBiggestSale() {
    Sale biggestSale = null;
    for (List<Sale> sales : map.values()) {
     Sale biggestSaleForSalesman

     = Collections.max(sales, SALE_COST_COMPARATOR);
    

    if (biggestSale == null

     || biggestSaleForSalesman.getCharge() > biggestSale().getCharge()) {
    

    biggestSale = biggestSaleForSalesman; } } return biggestSale; }</pre>
    現在這么寫(需要將map轉換成multimap):

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


    Joiner的用法:
    以前這樣寫:
    public class ShoppingList {
    private List<Item> items = ...;

    ...

    public String toString() { StringBuilder stringBuilder = new StringBuilder(); for (Iterator<Item> s = items.iterator(); s.hasNext(); ) { stringBuilder.append(s.next()); if (s.hasNext()) { stringBuilder.append(" and "); } } return stringBuilder.toString(); } }</pre>
    現在這樣寫:

    public class ShoppingList {
    private List<Item> items = ...;

    ...

    public String toString() { return Join.join(" and ", items); } }</pre>

    Comparators.fromFunction的用法:
    以前這樣寫:

     public Comparator<Product> createRetailPriceComparator(
    final CurrencyConverter currencyConverter) {
    return new Comparator<Product>() {
    public int compare(Product a, Product b) {
      return getRetailPriceInUsd(a).compareTo(getRetailPriceInUsd(b));
    }
    public Money getRetailPriceInUsd(Product product) {
      Money retailPrice = product.getRetailPrice();
      return retailPrice.getCurrency() == CurrencyCode.USD

      ? retailPrice
      : currencyConverter.convert(retailPrice, CurrencyCode.USD);
    

    } }; }</pre>
    現在這樣寫(感覺也沒省多少):

     public Comparator<Product> createRetailPriceComparator(
    final CurrencyConverter currencyConverter) {
    return Comparators.fromFunction(new Function<Product,Money>() {
    /* returns the retail price in USD /
    public Money apply(Product product) {
      Money retailPrice = product.getRetailPrice();
      return retailPrice.getCurrency() == CurrencyCode.USD

      ? retailPrice
      : currencyConverter.convert(retailPrice, CurrencyCode.USD);
    

    } }); }</pre>

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

     private static final Map<Integer, String> NUMBER_TO_NAME;
    private static final Map<String, Integer> NAME_TO_NUMBER;

    static { NUMBER_TO_NAME = Maps.newHashMap(); NUMBER_TO_NAME.put(1, "Hydrogen"); NUMBER_TO_NAME.put(2, "Helium"); NUMBER_TO_NAME.put(3, "Lithium");

    / reverse the map programatically so the actual mapping is not repeated / NAME_TO_NUMBER = Maps.newHashMap(); for (Integer number : NUMBER_TO_NAME.keySet()) { NAME_TO_NUMBER.put(NUMBER_TO_NAME.get(number), number); } }

    public static int getElementNumber(String elementName) { return NUMBER_TO_NAME.get(elementName); }

    public static string getElementName(int elementNumber) { return NAME_TO_NUMBER.get(elementNumber); }</pre>
    現在的用法:

     private static final BiMap<Integer,String> NUMBER_TO_NAME_BIMAP;

    static { NUMBER_TO_NAME_BIMAP = Maps.newHashBiMap(); NUMBER_TO_NAME_BIMAP.put(1, "Hydrogen"); NUMBER_TO_NAME_BIMAP.put(2, "Helium"); NUMBER_TO_NAME_BIMAP.put(3, "Lithium"); }

    public static int getElementNumber(String elementName) { return NUMBER_TO_NAME_BIMAP.inverse().get(elementName); }

    public static string getElementName(int elementNumber) { return NUMBER_TO_NAME_BIMAP.get(elementNumber); }</pre>
    換一種寫法:

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


    關于Strings的一些用法(http://blog.ralscha.ch/?p=888):
    assertEquals("test", Strings.emptyToNull("test"));
    assertEquals(" ", Strings.emptyToNull(" "));
    assertNull(Strings.emptyToNull(""));
    assertNull(Strings.emptyToNull(null));

assertFalse(Strings.isNullOrEmpty("test")); assertFalse(Strings.isNullOrEmpty(" ")); assertTrue(Strings.isNullOrEmpty("")); assertTrue(Strings.isNullOrEmpty(null));

assertEquals("test", Strings.nullToEmpty("test")); assertEquals(" ", Strings.nullToEmpty(" ")); assertEquals("", Strings.nullToEmpty("")); assertEquals("", Strings.nullToEmpty(null));

assertEquals("Ralph_", Strings.padEnd("Ralph", 10, '')); assertEquals("Bob__", Strings.padEnd("Bob", 10, '_'));

assertEquals("_Ralph", Strings.padStart("Ralph", 10, '_')); assertEquals("___Bob", Strings.padStart("Bob", 10, '_'));

assertEquals("xyxyxyxyxy", Strings.repeat("xy", 5));</pre>

Throwables的用法(將檢查異常轉換成未檢查異常):

package com.ociweb.jnb.apr2010;

import com.google.common.base.Throwables;

import java.io.InputStream; import java.net.URL;

public class ExerciseThrowables { public static void main(String[] args) { try { URL url = new URL("
Multimap用法整理(
http://jnb.ociweb.com/jnb/jnbApr2008.html):
用來統計多值出現的頻率:

        Multimap<Integer, String> siblings = Multimaps.newHashMultimap();
        siblings.put(0, "Kenneth");
        siblings.put(1, "Joe");
        siblings.put(2, "John");
        siblings.put(3, "Jerry");
        siblings.put(3, "Jay");
        siblings.put(5, "Janet");

    for (int i = 0; i < 6; i++) {
        int freq = siblings.get(i).size();
        System.out.printf("%d siblings frequency %d\n", i, freq);
    }</pre> <br />

輸出結果:

引用

        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(閉包功能)

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


不過這種轉換是在訪問元素的時候才進行, 下面的例子可以說明:

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



 本文由用戶 ptjs 自行上傳分享,僅供網友學習交流。所有權歸原作者,若您的權利被侵害,請聯系管理員。
 轉載本站原創文章,請注明出處,并保留原始鏈接、圖片水印。
 本站是一個以用戶分享為主的開源技術平臺,歡迎各類分享!