天天看點

Guava代碼學習筆記

Guava 是一個 Google 的基于java1.6的類庫集合的擴充項目,包括 collections, caching, primitives support, concurrency libraries, common annotations, string processing, I/O, 等等. 這些高品質的 API 可以使你的JAVa代碼更加優雅,更加簡潔,讓你工作更加輕松愉悅。

項目相關資訊:

  官方首頁:http://code.google.com/p/guava-libraries

  官方下載下傳:http://code.google.com/p/guava-libraries/downloads/list

  官方文檔:http://docs.guava-libraries.googlecode.com/git/javadoc

                    http://www.ostools.net/apidocs/apidoc?api=guava

    線上文檔檢視:http://www.boyunjian.com/javadoc/com.google.guava/guava-jdk5/14.0.1/_/com/google/common/base/Objects.ToStringHelper.html

  源碼包的簡單說明: 

  com.google.common.annotations:普通注解類型。 

  com.google.common.base:基本工具類庫和接口。 

  com.google.common.cache:緩存工具包,非常簡單易用且功能強大的JVM内緩存。 

  com.google.common.collect:帶泛型的集合接口擴充和實作,以及工具類,這裡你會發現很多好玩的集合。 

  com.google.common.eventbus:釋出訂閱風格的事件總線。 

  com.google.common.hash: 哈希工具包。 

  com.google.common.io:I/O工具包。 

  com.google.common.math:原始算術類型和超大數的運算工具包。 

  com.google.common.net:網絡工具包。 

  com.google.common.primitives:八種原始類型和無符号類型的靜态工具包。 

  com.google.common.reflect:反射工具包。 

  com.google.common.util.concurrent:多線程工具包。

最新的maven坐标:

<dependency>
	<groupId>com.google.guava</groupId>
	<artifactId>guava</artifactId>
	<version>19.0</version>
</dependency>
           

類庫使用手冊:

  一.  基本工具類:讓使用Java語言更令人愉悅。

  1. 使用和避免 null:null 有語言歧義, 會産生令人費解的錯誤, 反正他總是讓人不爽。很多 Guava 的工具類在遇到 null 時會直接拒絕或出錯,而不是默默地接受他們。

  2. 前提條件:更容易的對你的方法進行前提條件的測試。

  3. 常見的對象方法: 簡化了Object常用方法的實作, 如 hashCode() 和 toString()。

  4. 排序: Guava 強大的 "fluent Comparator"比較器, 提供多關鍵字排序。

  5. Throwable類: 簡化了異常檢查和錯誤傳播。

  二.  集合類:集合類庫是 Guava 對 JDK 集合類的擴充, 這是 Guava 項目最完善和為人所知的部分。

  1. Immutable collections(不變的集合): 防禦性程式設計, 不可修改的集合,并且提高了效率。

  2. New collection types(新集合類型):JDK collections 沒有的一些集合類型,主要有:multisets,multimaps,tables, bidirectional maps等等

  3. Powerful collection utilities(強大的集合工具類): java.util.Collections 中未包含的常用操作工具類

  4. Extension utilities(擴充工具類): 給 Collection 對象添加一個裝飾器? 實作疊代器? 我們可以更容易使用這些方法。

  三.  緩存: 本地緩存,可以很友善的操作緩存對象,并且支援各種緩存失效行為模式。

  四.  Functional idioms(函數式): 簡潔, Guava實作了Java的函數式程式設計,可以顯著簡化代碼。

  五. Concurrency(并發):強大,簡單的抽象,讓我們更容易實作簡單正确的并發性代碼。

  1. ListenableFuture(可監聽的Future): Futures,用于異步完成的回調。

  2. Service: 控制事件的啟動和關閉,為你管理複雜的狀态邏輯。

  六. Strings: 一個非常非常有用的字元串工具類: 提供 splitting,joining, padding 等操作。

  七. Primitives: 擴充 JDK 中未提供的對原生類型(如int、char等)的操作, 包括某些類型的無符号的變量。

  八. Ranges: Guava 一個強大的 API,提供 Comparable 類型的範圍處理, 包括連續和離散的情況。

  九. I/O: 簡化 I/O 操作, 特别是對 I/O 流和檔案的操作, for Java 5 and 6.

  十. Hashing: 提供比 Object.hashCode() 更複雜的 hash 方法, 提供 Bloom filters.

  十一. EventBus: 基于釋出-訂閱模式的元件通信,但是不需要明确地注冊在委托對象中。

  十二. Math: 優化的 math 工具類,經過完整測試。

  十三. Reflection: Guava 的 Java 反射機制工具類。

集合API的使用

 1簡化工作

可以簡化集合的建立和初始化;

類别 原來的寫法 guava的寫法
集合建立

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

List<List<Map<String, String>>> list = new ArrayList<List<Map<String,String>>>();

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

List<List<Map<String, String>>> list = Lists.newArrayList();

//1,簡化集合的建立

List<Person> personList= Lists.newLinkedList();

Set<Person> personSet= Sets.newHashSet();

Map<String,Person> personMap= Maps.newHashMap();

Integer[] intArrays= ObjectArrays.newArray(Integer.class,10);

集合初始化

Set<String> set = new HashSet<String>();

set.add("one");

set.add("two");

set.add("three");

Set<String> set = Sets.newHashSet("one","two","three");

List<String> list = Lists.newArrayList("one","two","three");

Map<String, String> map = ImmutableMap.of("ON","TRUE","OFF","FALSE");

//2,簡化集合的初始化

List<Person> personList2= Lists.newArrayList(new Person(1, 1, "a", "46546", 1, 20),

new Person(2, 1, "a", "46546", 1, 20));

Set<Person> personSet2= Sets.newHashSet(new Person(1,1,"a","46546",1,20),

new Person(2,1,"a","46546",1,20));

Map<String,Person> personMap2= ImmutableMap.of("hello",new Person(1,1,"a","46546",1,20),"fuck",new Person(2,1,"a","46546",1,20));

建立不可變的集合

ImmutableList<Person> personImmutableList=
ImmutableList.of(new Person(1, 1, "a", "46546", 1, 20), new Person(2, 1, "a", "46546", 1, 20));

ImmutableSet<Person> personImmutableSet=ImmutableSet.copyOf(personSet2);

ImmutableMap<String,Person> personImmutableMap=ImmutableMap.<String,Person>builder()
.put("hell",new Person(1,1,"a","46546",1,20)).putAll(personMap2) .build();
           

新的集合類型

The Guava API provides very useful new collection types that work very nicely with existing java collections.

guava API 提供了有用的新的集合類型,協同已經存在的java集合工作的很好。

分别是 MultiMap, MultiSet, Table, BiMap, ClassToInstanceMap

種類 寫的例子
MultiMap

一種key可以重複的map,子類有ListMultimap和SetMultimap,對應的通過key分别得到list和set

Multimap<String, Person> customersByType =ArrayListMultimap.create();customersByType.put("abc", new Person(1, 1, "a", "46546", 1, 20));

customersByType.put("abc", new Person(1, 1, "a", "46546", 1, 30));

customersByType.put("abc", new Person(1, 1, "a", "46546", 1, 40));

customersByType.put("abc", new Person(1, 1, "a", "46546", 1, 50));

customersByType.put("abcd", new Person(1, 1, "a", "46546", 1, 50));

customersByType.put("abcde", new Person(1, 1, "a", "46546", 1, 50));

for(Person person:customersByType.get("abc"))

{

System.out.println(person.getAge());

}

MultiSet

不是集合,可以增加重複的元素,并且可以統計出重複元素的個數,例子如下:

private static void testMulitiSet() {

Multiset<Integer> multiSet = HashMultiset.create();

multiSet.add(10);

multiSet.add(30);

multiSet.add(30);

multiSet.add(40);

System.out.println( multiSet.count(30)); // 2

System.out.println( multiSet.size()); //4

}

Table

相當于有兩個key的map,不多解釋

private static void testTable() {

Table<Integer,Integer,Person> personTable=HashBasedTable.create();

personTable.put(1,20,new Person(1, 1, "a", "46546", 1, 20));

personTable.put(0,30,new Person(2, 1, "ab", "46546", 0, 30));

personTable.put(0,25,new Person(3, 1, "abc", "46546", 0, 25));

personTable.put(1,50,new Person(4, 1, "aef", "46546", 1, 50));

personTable.put(0,27,new Person(5, 1, "ade", "46546",0, 27));

personTable.put(1,29,new Person(6, 1, "acc", "46546", 1, 29));

personTable.put(0,33,new Person(7, 1, "add", "46546",0, 33));

personTable.put(1,66,new Person(8, 1, "afadsf", "46546", 1, 66));

//1,得到行集合

Map<Integer,Person> rowMap= personTable.row(0);

int maxAge= Collections.max(rowMap.keySet());

}

BiMap

是一個一一映射,可以通過key得到value,也可以通過value得到key; 

private static void testBitMap() {

//雙向map

BiMap<Integer,String> biMap=HashBiMap.create();

biMap.put(1,"hello");

biMap.put(2,"helloa");

biMap.put(3,"world");

biMap.put(4,"worldb");

biMap.put(5,"my");

biMap.put(6,"myc");

int value= biMap.inverse().get("my");

System.out.println("my --"+value);

}

ClassToInstanceMap   有的時候,你的map的key并不是一種類型,他們是很多類型,你想通過映射他們得到這種類型,guava提供了ClassToInstanceMap滿足了這個目的。   除了繼承自Map接口,ClassToInstaceMap提供了方法  T getInstance(Class<T>) 和  T putInstance(Class<T>, T),消除了強制類型轉換。   該類有一個簡單類型的參數,通常稱為B,代表了map控制的上層綁定,例如:  
ClassToInstanceMap<Number> numberDefaults = MutableClassToInstanceMap.create();
numberDefaults.putInstance(Integer.class, Integer.valueOf(0));      

從技術上來說, ClassToInstanceMap<B> 實作了 Map<Class<? extends B>, B>,或者說,這是一個從B的子類到B對象的映射,這可能使得 ClassToInstanceMap的泛型輕度混亂,但是隻要記住B總是Map的上層綁定類型,通常來說B隻是一個對象。 guava提供了有用的實作,   MutableClassToInstanceMap  和   ImmutableClassToInstanceMap . 重點:像其他的Map<Class,Object>, ClassToInstanceMap 含有的原生類型的項目,一個原生類型和他的相應的包裝類可以映射到不同的值;

private static void testClass() {

ClassToInstanceMap<Person> classToInstanceMap =MutableClassToInstanceMap.create();

Person person= new Person(1,20,"abc","46464",1,100);

classToInstanceMap.putInstance(Person.class,person);

// System.out.println("string:"+classToInstanceMap.getInstance(String.class));

// System.out.println("integer:" + classToInstanceMap.getInstance(Integer.class));

Person person1=classToInstanceMap.getInstance(Person.class);

}

 排序

 是guava一份非常靈活的比較類,可以被用來操作,擴充,當作比較器,排序提供了集合排序的很多控制;

執行個體如下:

Lists.newArrayList(30, 20, 60, 80, 10);

Ordering.natural().sortedCopy(numbers); //10,20,30,60,80

Ordering.natural().reverse().sortedCopy(numbers); //80,60,30,20,10

Ordering.natural().min(numbers); //10

Ordering.natural().max(numbers); //80

Lists.newArrayList(30, 20, 60, 80, null, 10);

Ordering.natural().nullsLast().sortedCopy(numbers); //10, 20,30,60,80,null

Ordering.natural().nullsFirst().sortedCopy(numbers); //null,10,20,30,60,80

 

public static void testOrdering()
{
List<Person> personList=Lists.newArrayList(
new Person(3, 1, "abc", "46546", 0, 25),
new Person(2, 1, "ab", "46546", 0, 30),
new Person(5, 1, "ade", "46546",0, 27),
new Person(1, 1, "a", "46546", 1, 20),
new Person(6, 1, "acc", "46546", 1, 29),
new Person(4, 1, "aef", "46546", 1, 50),
new Person(7, 1, "add", "46546",0, 33)
);

Ordering<Person> byAge=new Ordering<Person>() {
@Override
public int compare( Person left, Person right) {
return right.getAge()-left.getAge();
}
};

for(Person p: byAge.immutableSortedCopy(personList))
{
System.out.println(p);
}
}
           

下面的例子為Guava重寫的toString()方法的例子:

// 重寫PhoneNumber的toString方法 - Effective Java中文第二版第44頁
package org.effectivejava.examples.chapter03.item10;

import java.util.HashMap;
import java.util.Map;

import com.google.common.base.Objects;

public final class PhoneNumber {
        private final short areaCode;
        private final short prefix;
        private final short lineNumber;

        public PhoneNumber(int areaCode, int prefix, int lineNumber) {
                rangeCheck(areaCode, 999, "area code");
                rangeCheck(prefix, 999, "prefix");
                rangeCheck(lineNumber, 9999, "line number");
                this.areaCode = (short) areaCode;
                this.prefix = (short) prefix;
                this.lineNumber = (short) lineNumber;
        }

        private static void rangeCheck(int arg, int max, String name) {
                if (arg < 0 || arg > max)
                        throw new IllegalArgumentException(name + ": " + arg);
        }

        @Override
        public boolean equals(Object o) {
                if (o == this)
                        return true;
                if (!(o instanceof PhoneNumber))
                        return false;
                PhoneNumber pn = (PhoneNumber) o;
                return pn.lineNumber == lineNumber && pn.prefix == prefix
                                && pn.areaCode == areaCode;
        }

        @Override
        public int hashCode() {
                int result = 17;
                result = 31 * result + areaCode;
                result = 31 * result + prefix;
                result = 31 * result + lineNumber;
                return result;
        }

    //Effective Java原有的toString方法
        /*
         * @Override public String toString() { return
         * String.format("(%03d) %03d-%04d", areaCode, prefix, lineNumber); }
         */

        /**
         * 采用Guava實作的toString
         *
         */
        @Override
        public String toString() {
                return Objects.toStringHelper(this)
                                .addValue(String.format("(%03d) %03d-%04d", areaCode, prefix,lineNumber))
                                .add("areaCode", areaCode)
                                .add("prefix", prefix)
                                .add("lineNumber", lineNumber)
                                .toString();
        }

        public static void main(String[] args) {
                Map<PhoneNumber, String> m = new HashMap<PhoneNumber, String>();
                m.put(new PhoneNumber(707, 867, 5309), "Jenny");

                System.out.println(m);
        }
}
           

輸出結果如下:

//原輸出
{(707) 867-5309=Jenny}  

//Guava實作輸出 
{PhoneNumber{(707) 867-5309, areaCode=707, prefix=867, lineNumber=5309}=Jenny}