Guava工具包含了若干被Google的 Java項目廣泛依賴 的核心庫,例如:
- 集合 [collections]
- 緩存 [caching]
- 原生類型支持 [primitives support]
- 併發庫 [concurrency libraries]
- 通用註解 [common annotations]
- 字符串處理 [string processing]
- I/O 等等
引用
<dependency>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
<version>26.0</version>
</dependency>
集合:
不可變集合
不可變對象有很多優點,包括:
- 當對象被不可信的庫調用時,不可變形式是安全的;
- 不可變對象被多個線程調用時,不存在競態條件問題
- 不可變集合不需要考慮變化,因此可以節省時間和空間。所有不可變的集合都比它們的可變形式有更好的內存利用率(分析和測試細節);
- 不可變對象因爲有固定不變,可以作爲常量來安全使用。
JDK也提供了Collections.unmodifiableXXX方法把集合包裝爲不可變形式,但我們認爲不夠好:
- 笨重而且累贅:不能舒適地用在所有想做防禦性拷貝的場景;
- 不安全:要保證沒人通過原集合的引用進行修改,返回的集合纔是事實上不可變的;
- 低效:包裝過的集合仍然保有可變集合的開銷,比如併發修改的檢查、散列表的額外空間,等等。
不可變集合的創建:copyof、of、builder方法、asList 視圖
新集合類型:
- Multiset:既有ArrayList語義,也有map語義
- SortedMultiset:支持高效獲取指定範圍的子集
- Multimap:將一個鍵映射到多個值
- BiMap:實現鍵值的雙向映射
- Table:實現表結構,使用多個值做索引
- ClassToInstanceMap:鍵是類型,值是符合鍵所指類型的對象
ClassToInstanceMap<Number> numberDefaults=MutableClassToInstanceMap.create();
numberDefaults.putInstance(Integer.class, Integer.valueOf(0));
- RangeSet:描述一組不相連的、非空的區間。當添加新的區間時,所有相連的區間會被合併,空區間會被忽略
- RangeMap:描述了不相交、非空的區間到特定值的映射。不會合並相鄰的映射
Collections中未包含的集合工具:
- Iterables
- FluentIterable
Lists方法:partition、reverse
集合方法:union、intersection、difference、symmetricDifference、cartesianProduct(返回所有笛卡爾積)、powerSet(所有子集)
Maps方法:
- uniqueIndex(有一組對象,在某個屬性上分別有獨一無二的值,而希望能夠按照這個屬性值查找對象)
- index(有一組對象,他們有共同的特定屬性,希望按照這個屬性的值查詢對象,但屬性值不一定是獨一無二的)
- difference、entriesInCommon、entriesDiffering、entriesOnlyOnLeft、entriesOnlyOnRight
- invertFrom(Miltimap 多個鍵可以映射到同一個值,invertFrom後也可以將值映射到多個鍵)
- forMap 把Map包裝成SetMultimap
Table
transpose 將table表進行轉置
集合創建:
// 普通Collection的創建
List<String> list = Lists.newArrayList();
Set<String> set = Sets.newHashSet();
Map<String, String> map = Maps.newHashMap();
// 不變Collection的創建
ImmutableList<String> iList = ImmutableList.of("a", "b", "c");
ImmutableSet<String> iSet = ImmutableSet.of("e1", "e2");
ImmutableMap<String, String> iMap = ImmutableMap.of("k1", "v1", "k2", "v2");
Multiset<String> set1 = HashMultiset.create();
set1.add("a");
set1.add("2");
set1.add("a");
System.out.println("set1 = " + set1.toString());
//計算出現次數
System.out.println("count= " + set1.count("a"));
//key可以重複
Multimap<String, Integer> multimap = ArrayListMultimap.create();
multimap.put("a", 1);
multimap.put("a", 1);
System.out.println("multimap = " + multimap);
//雙向map 鍵和值都不能重複
BiMap<String, String> biMap = HashBiMap.create();
biMap.put("a", "1");
biMap.put("b", "2");
System.out.println("bimap key " + biMap.get("a"));
System.out.println("bimap value " + biMap.inverse().get("1"));
//Table 比較常用 <row, column ,value>
Table<String, String, Integer> tables = HashBasedTable.create();
tables.put("row1", "column1",1);
tables.put("row2","column2", 2);
System.out.println("the row1 is " + tables.row("row1"));
System.out.println("the row1 cloumn is " + tables.column("column1"));
System.out.println("the value is " + tables.get("row1", "column1"));
擴展工具類
在元素添加到列表時增加特定行爲
- Forwarding裝飾器:delegate,覆蓋這個方法返回被裝飾的對象,實現特定行爲
- PeekingIterator:事先獲取下次next返回的元素
- AbstractIterator:實現自己的Iterator
- AbstractSequentialIerator:表示迭代的另一種方式
集合的過濾
(1)按照條件過濾
ImmutableList<String> names = ImmutableList.of("begin", "code", "Guava", "Java");
Iterable<String> fitered = Iterables.filter(names, Predicates.or(Predicates.equalTo("Guava"), Predicates.equalTo("Java")));
System.out.println(fitered); // [Guava, Java]
(2)自定義過濾條件
//自定義過濾條件 使用自定義回調方法對Map的每個Value進行操作
ImmutableMap<String, Integer> m = ImmutableMap.of("begin", 12, "code", 15);
// Function<F, T> F表示apply()方法input的類型,T表示apply()方法返回類型
Map<String, Integer> m2 = Maps.transformValues(m, new Function<Integer, Integer>() {
public Integer apply(Integer input) {
if(input>12){
return input;
}else{
return input+1;
}
}
});
System.out.println(m2); //{begin=13, code=15}
(3)set的交集、並集、差集
HashSet<Integer> setA = Sets.newHashSet(1, 2, 3, 4, 5);
HashSet<Integer> setB = Sets.newHashSet(4, 5, 6, 7, 8);
Sets.SetView<Integer> union = Sets.union(setA, setB);
System.out.println("union:");
for (Integer integer : union){
System.out.println(integer);//union:12345867
}
Sets.SetView<Integer> difference = Sets.difference(setA, setB);
System.out.println("difference:");
for (Integer integer : difference){
System.out.println(integer); //difference:123
}
Sets.SetView<Integer> intersection = Sets.intersection(setA, setB);
System.out.println("intersection:");
for (Integer integer : intersection){
System.out.println(integer);
}
(4)map的交集、並集、差集
Map<String, Integer> mapA = Maps.newHashMap();
Map<String, Integer> mapB = Maps.newHashMap();
mapA.put("a", 1);
mapA.put("b", 2);
mapA.put("c", 6);
mapB.put("d", 4);
mapB.put("c", 3);
MapDifference<String, Integer> difference1 = Maps.difference(mapA, mapB);
System.out.println("are qual " + difference1.areEqual());
System.out.println("diff " + difference1.entriesDiffering());
System.out.println("left " + difference1.entriesOnlyOnLeft());
System.out.println("right" + difference1.entriesOnlyOnRight());
System.out.println("common" + difference1.entriesInCommon());
字符串操作
(1) 連接器Joiner
將集合轉換爲特定規則的字符串,核心是Joiner類
list->string
List<String> list = Lists.newArrayList();
list.add("a");
list.add("b");
list.add("c");
String result = Joiner.on(",").join(list);
System.out.println("the string is " + result);
map->String
Map<String, String> map1 = Maps.newHashMap();
map1.put("zhangruizhi", "hehe");
map1.put("zhang", "haha");
String resultMap = Joiner.on(",").withKeyValueSeparator("=").join(map1);
System.out.println("the result map is " + resultMap);
連接器Joiner
Joiner joiner = Joiner.on("; ").skipNulls();
return joiner.join("Harry", null, "Ron", "Hermione");
(2) 拆分器Splitter
將字符串轉換爲特定規則的集合,核心是Splitter類
string->list,可以忽略空格,空行
String s = "192.168.0.1, 192.168.0.2, 192.168.0.3, 192.168.0.4";
List<String> sList = Splitter.on(",").omitEmptyStrings().trimResults().splitToList(s);
System.out.println("the sList is " + sList);
string->map
String mapS = "zhangruizhi=a, zhang=b";
Map<String, String> sMap = Splitter.on(",").withKeyValueSeparator("=").split(mapS);
System.out.println("the s map is " + sMap);
拆分器Splitter
Splitter.on(',')
.trimResults()
.omitEmptyStrings()
.split("foo,bar,, qux");
字符匹配器CharMatcher
String noControl = CharMatcher.JAVA_ISO_CONTROL.removeFrom(string); //移除control字符
String theDigits = CharMatcher.DIGIT.retainFrom(string); //只保留數字字符
String spaced = CharMatcher.WHITESPACE.trimAndCollapseFrom(string, ' ');
//去除兩端的空格,並把中間的連續空格替換成單個空格
String noDigits = CharMatcher.JAVA_DIGIT.replaceFrom(string, "*"); //用*號替換所有數字
String lowerAndDigit = CharMatcher.JAVA_DIGIT.or(CharMatcher.JAVA_LOWER_CASE).retainFrom(string);
// 只保留數字和小寫字母
字符集Charsets
大小寫格式CaseFormat
CaseFormat.UPPER_UNDERSCORE.to(CaseFormat.LOWER_CAMEL, "CONSTANT_NAME")); // returns "constantName"
計時工具
Stopwatch stopwatch = Stopwatch.createStarted();
int sum = 0;
for( int i =0; i< 100; i++){
sum+=i;
}
long time = stopwatch.elapsed(TimeUnit.MICROSECONDS);
文件操作
主要是Files類
File file = new File("/test.txt");
List<String> listTest = null;
try {
list = Files.readLines(file, Charsets.UTF_8);
} catch (Exception e) {
}
File from = new File("./test.log");
File to = new File("./newFile.log");
File directory = new File("./.");
try{
Files.copy(from,to); //複製文件
Files.move(from, to); //移動文件
URL url = Resources.getResource("abc.xml"); //獲取classpath根下的abc.xml文件url
}catch (IOException ioe){
}
緩存
Guava Cache適用於:
- 願意消耗一些內存空間來提升速度。
- 你預料到某些鍵會被查詢一次以上。
- 緩存中存放的數據總量不會超出內存容量。
LoadingCache<Key, Graph> graphs = CacheBuilder.newBuilder()
.maximumSize(1000)
.expireAfterWrite(10, TimeUnit.MINUTES)
.removalListener(MY_LISTENER)
.build(
new CacheLoader<Key, Graph>() {
public Graph load(Key key) throws AnyException {
return createExpensiveGraph(key);
}
});
緩存回收:基於容量的回收、定時回收、基於引用的回收、顯式清除
Guava 數學運算
- Guava Math針對各種不常見的溢出情況都有充分的測試;對溢出語義,Guava文檔也有相應的說明;如果運算的溢出檢查不能通過,將導致快速失敗;
- Guava Math的性能經過了精心的設計和調優;雖然性能不可避免地依據具體硬件細節而有所差異,但Guava Math的速度通常可以與Apache Commons的MathUtils相比,在某些場景下甚至還有顯著提升;
- Guava Math在設計上考慮了可讀性和正確的編程習慣;IntMath.log2(x, CEILING) 所表達的含義,即使在快速閱讀時也是清晰明確的。而32-Integer.numberOfLeadingZeros(x – 1)對於閱讀者來說則不夠清晰。
基本使用
Optional
對null值進行快速失敗
Optional<T> 表示可能的null的T類型的引用
Optional.of(T) | 創建指定引用的Optional實例,若引用爲null則快速失敗 |
Optional.absent() | 創建引用缺失的Optional實例 |
Optional.fromNullable(T) | 創建指定引用的Optional實例,若引用爲null則表示缺失 |
Preconditions
若干前置條件判斷的方法
checkArgument(boolean) | 檢查boolean是否爲true,用來檢查傳遞給方法的參數。 | IllegalArgumentException |
checkNotNull(T) | 檢查value是否爲null,該方法直接返回value,因此可以內嵌使用checkNotNull。 | NullPointerException |
checkState(boolean) | 用來檢查對象的某些狀態。 | IllegalStateException |
checkElementIndex(int index, int size) | 檢查index作爲索引值對某個列表、字符串或數組是否有效。index>=0 && index<size * | IndexOutOfBoundsException |
checkPositionIndex(int index, int size) | 檢查index作爲位置值對某個列表、字符串或數組是否有效。index>=0 && index<=size * | IndexOutOfBoundsException |
checkPositionIndexes(int start, int end, int size) | 檢查[start, end]表示的位置範圍對某個列表、字符串或數組是否有效* | IndexOutOfBoundsException |
參數檢查 主要是Preconditions類
String testString = null;
Preconditions.checkArgument(!Strings.isNullOrEmpty(testString), "the testString is null or empty");
String testString1 = null;
Preconditions.checkNotNull(testString1);
Ordering
用來構建複雜的比較器,完成集合排序的功能
創建排序器:
natural() | 對可排序類型做自然排序,如數字按大小,日期按先後排序 |
usingToString() | 按對象的字符串形式做字典排序[lexicographical ordering] |
from(Comparator) | 把給定的Comparator轉化爲排序器 |
鏈式調用方法: 後面的方法包裝了前面的排序器
reverse() | 獲取語義相反的排序器 |
nullsFirst() | 使用當前排序器,但額外把null值排到最前面。 |
nullsLast() | 使用當前排序器,但額外把null值排到最後面。 |
compound(Comparator) | 合成另一個比較器,以處理當前排序器中的相等情況。 |
lexicographical() | 基於處理類型T的排序器,返回該類型的可迭代對象Iterable<T>的排序器。 |
onResultOf(Function) | 對集合中元素調用Function,再按返回值用當前排序器排序。 |
運用排序器:
Throwables:簡化異常和錯誤的傳播與檢查
Throwables.propagate
參考:
https://www.cnblogs.com/peida/archive/2013/06/08/3120820.html
https://wizardforcel.gitbooks.io/guava-tutorial/content/1.html