Google Guava學習筆記
阿新 • • 發佈:2019-02-08
Java Collection Framework的增強工具類Google Guava Collection
使用這個工具包的主要原因是為了當使用collection等類處理複雜邏輯的時候,可以使用Guava collection幫助完成這些工作。使得程式碼等短,程式碼質量更高,同時更容易閱讀和修改。
功能舉例:
Multiset: 能夠把重複的元素放入一個集合,並且可以統計元素數量
Multimap:能夠實現同一個key對應多個元素,不用自己繁瑣地實現
BiMap:key不重複,value也不重複
Ordering: 作為比較器進行排序,簡化程式碼
如果你對上述功能有興趣,那請你繼續閱讀。
首先我們構建一個Company類
上述例子主要實現了Function的主功能,把一個集合類companies從Company類轉換為String型別,利用了guava包中的集合工具類都有的transform方法,通過傳入原始集合和function例項,生成新的集合,只要實現了function介面類中的apply方法就可以了,其中泛型中第一個引數是原始集合的型別,第二個引數是目的集合的型別。還可以使用對應的工具類Functions的compose方法進行組合的Function運算,應對複雜的演算法邏輯。同時,還有對應map方法,通過Functions的forMap方法,將map中value值通過function轉換為新的collection。
Predicate類,與Function類類似,這裡也提供一個PredicateTest來進行測試。
與Function介面類似,Predicate介面類也是需要實現其apply的方法,並使用Guava包中集合工具類的filter方法對集合元素進行過濾。當然,也提供對應的工具類Predicates的and,or,not等方法進行復雜邏輯的過濾,並提供諸如Predicates.notNull或Predicates.alwaysTrue等簡單的predicate例項方法。
下面貼出我看的兩個包Base包和collect包和其測試方法。僅供參考,如有問題,請留言,我會盡快回復。
PreconditionsTest
Collection包:
SetsTest
MapsTest
IteralbesTest
OrdingTest
SpecificalMapTest有趣的方法都在這裡了,請詳閱
Primitive包
guava中文 api(不全)
the latest version: guava-18.0.jar about guava api
函數語言程式設計:Function和Predicate
Function類:通過Function類將指定的集合類轉變為我們想要的集合類 Predicate類:通過Predicate類將制定的集合類進行過濾,從而剔除集合中不想要的元素首先我們構建一個Company類
其次我們構建一個FunctionTest,用於測試Function類的功能:package rich.model; import java.util.Arrays; import java.util.List; import com.google.common.collect.Lists; public class Company { private List<Company> companies; private String name; private String location; public static Company newCompany(String name, String loc) { Company company = new Company(); company.setName(name); company.setLocation(loc); return company; } public void init() { companies = Lists.newArrayList(); companies.addAll(Arrays.asList(Company.newCompany("quest", "zhuhai"),Company.newCompany("dell", "toronto"))); } public String getName() { return name; } public void setName(String name) { this.name = name; } public String getLocation() { return location; } public void setLocation(String location) { this.location = location; } public List<Company> getCompanies() { return companies; } public void setCompanies(List<Company> companies) { this.companies = companies; } }
package rich.base; import java.util.Collection; import java.util.Iterator; import java.util.List; import java.util.Map; import rich.model.Company; import com.google.common.base.Function; import com.google.common.collect.Collections2; import com.google.common.collect.Lists; import com.google.common.collect.Maps; import com.google.common.base.Functions; public class FunctionTest { public static void main(String[] args) { //介面Function<F,T> {T apply(F input) } //把一種形式的Collection<F>轉換成另一種Collection<T> Function<Company, String> function1 = new Function<Company, String>() { @Override public String apply(Company company) { return company.getLocation(); } }; //進行轉換 Company company = new Company(); company.init(); List<String> companyLocationList = Lists.transform(company.getCompanies(), function1); //Collection<String> collectionCompanyList = Collections2.transform(company.getCompanies(), function1); for(int i = 0; i < companyLocationList.size(); i++) { System.out.println(companyLocationList.get(i)); } //除此之外,還可以進行組合運算 //新function Function<String, String> function2 = new Function<String, String>() { @Override public String apply(String s) { return s.toUpperCase(); } }; //重新定義一個function3,將function1和function2組合在一起 //使用Functions的compose方法 Function<Company, String> function3 = Functions.compose(function2, function1); //轉換集合 Collection<String> upperLocationList = Collections2.transform(company.getCompanies(), function3); System.out.println(upperLocationList.contains("ZHUHAI")); //還有map方法 Map<Company, String> map = Maps.newHashMap(); map.put(company.getCompanies().get(0), "bigCompany"); //function4 Function<Company, String> function4 = Functions.forMap(map,"UNKNOWN"); //進行對映,即若有zhuhai這個物件,則返回bigCompany這個值 //如果物件沒有對應的map value,則返回default value "UNKNOWN" Collection<String> types = Collections2.transform(company.getCompanies(), function4); Iterator typeIterator = types.iterator(); while(typeIterator.hasNext()){ System.out.println(typeIterator.next()); } } }
上述例子主要實現了Function的主功能,把一個集合類companies從Company類轉換為String型別,利用了guava包中的集合工具類都有的transform方法,通過傳入原始集合和function例項,生成新的集合,只要實現了function介面類中的apply方法就可以了,其中泛型中第一個引數是原始集合的型別,第二個引數是目的集合的型別。還可以使用對應的工具類Functions的compose方法進行組合的Function運算,應對複雜的演算法邏輯。同時,還有對應map方法,通過Functions的forMap方法,將map中value值通過function轉換為新的collection。
Predicate類,與Function類類似,這裡也提供一個PredicateTest來進行測試。
package rich.base;
import java.util.Collection;
import java.util.Iterator;
import rich.model.Company;
import com.google.common.base.Functions;
import com.google.common.base.Predicate;
import com.google.common.base.Predicates;
import com.google.common.collect.Collections2;
public class PredicateTest {
public static void main(String[] args) {
//Predicate主要用於對Collection的值進行過濾
Predicate<Company> predicate1 = new Predicate<Company>(){
@Override
public boolean apply(Company company) {
if(company.getName() == "quest") {
return true;
} else
return false;
}
};
Company company = new Company();
company.init();
//進行過濾
Collection<Company> companyList1 = Collections2.filter(company.getCompanies(), predicate1);
Iterator<Company> c1 = companyList1.iterator();
while(c1.hasNext()) {
System.out.println(c1.next().getLocation());
}
//有一個Predicates類用於對Predicate介面進行操作,用法與Functions類似
Predicate<Company> predicate2 = new Predicate<Company>(){
@Override
public boolean apply(Company company) {
if(company.getLocation() == "zhuhai") {
return true;
} else
return false;
}
};
//and 和 or
Predicate<Company> predicateOr = Predicates.or(predicate1, predicate2);
//Predicate<Company> predicateOr = Predicates.and(predicate1, predicate2);
Collection<Company> companyList2 = Collections2.filter(company.getCompanies(), predicateOr);
Iterator<Company> c2 = companyList2.iterator();
while(c2.hasNext()) {
System.out.println(c2.next().getLocation());
}
//構造簡易的Predicate過濾集
Collection<Company> companyList3 = Collections2.filter(company.getCompanies(), Predicates.notNull());
//Collection<Company> companyList4 = Collections2.filter(company.getCompanies(), Predicates.alwaysTrue());
}
}
與Function介面類似,Predicate介面類也是需要實現其apply的方法,並使用Guava包中集合工具類的filter方法對集合元素進行過濾。當然,也提供對應的工具類Predicates的and,or,not等方法進行復雜邏輯的過濾,並提供諸如Predicates.notNull或Predicates.alwaysTrue等簡單的predicate例項方法。
下面貼出我看的兩個包Base包和collect包和其測試方法。僅供參考,如有問題,請留言,我會盡快回復。
Base包:
ObjectsTest
package rich.base;
import java.util.Collection;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import com.google.common.base.Joiner;
import com.google.common.base.MoreObjects;
import com.google.common.base.Objects;
import com.google.common.base.Splitter;
import com.google.common.base.Strings;
/*
* base 包大多是用於判斷值是否為空和判斷相等的方法集合包
*/
public class ObjectsTest {
public static void main(String[] args) {
//Objects
//判斷兩個物件是否相等。
System.out.println(Objects.equal("1", "2"));
//Objects的方法都移到了MoreObject上
//一般是用來判斷第一個引數值是否為空,若為空,則返回第二個引數的值。
System.out.println(MoreObjects.firstNonNull(null, 2));
//StringHelper是moreOjbects的靜態內部類,使用MoreObjects.toStringHelper獲得
MoreObjects.ToStringHelper stringHelper = MoreObjects.toStringHelper("MyObject").add("a", 1);
System.out.println(stringHelper);
//Strings
//判斷string為null或者“”
System.out.println(Strings.isNullOrEmpty(""));
//將空的string轉變為null物件,相對應的有nullToEmpty
System.out.println(Strings.emptyToNull(""));
//重複String
System.out.println(Strings.repeat("abc", 5));
//Joiner
//String有split方法,但String陣列沒有join方法
String[] joinStrArray = new String[]{"abc","bdc","dfg" };
//沒有迴圈的join方法, 還可以用skipNulls方法剔除null objects
Joiner joiner = Joiner.on(",");
String joinerString = joiner.join(joinStrArray);
//for(int i = 0; i < joinStrArray.size(); i++) { String joinerStr += (joinStrArray[i] + ",") } 更優雅一些,right?
System.out.println(joinerString);
//使用MapJoin
Map<String, String> joinMapArray = new HashMap<String, String>();
joinMapArray.put("lu", "rich");
joinMapArray.put("hong", "alex");
joinMapArray.put("wang", "sinba");
Joiner.MapJoiner mapJoiner = joiner.withKeyValueSeparator("-");
System.out.println(mapJoiner.join(joinMapArray));
//還可以加到StringBuilder中,不展開
//joinerString.split(",");是陣列
//Splitter
Splitter splitter = Splitter.on(",").trimResults();
//拿回上面使用的joinerString
Iterable<String> splitterStrArray = splitter.split(joinerString);
Iterator<String> iterator = splitterStrArray.iterator();
while(iterator.hasNext()) {
System.out.println(iterator.next());
}
//感覺原方法更好一些。
// String[] test = joinerString.split(",");
// for(int i = 0; i < test.length; i++) {
// System.out.println(test[i]);
// }
//Splitter也有mapSplitter方法
Splitter.MapSplitter mapSplitter = splitter.withKeyValueSeparator("-");
Map<String, String> mapSplitterArray = mapSplitter.split(mapJoiner.join(joinMapArray));
Collection<String> collectMap = mapSplitterArray.values();
Iterator<String> c = collectMap.iterator();
while(c.hasNext()) {
System.out.println(c.next());
}
}
}
PreconditionsTest
package rich.base;
import rich.model.Company;
import com.google.common.base.Preconditions;
public class PreconditionsTest {
public static void main(String[] args) {
Company company = new Company();
company.init();
//Preconditions用來檢查引數值是否符合預期
Preconditions.checkNotNull(company.getCompanies().get(0), "Check whether has a null object");
//如果為null值,則會拋exception,並提示errorMessage
Preconditions.checkNotNull(null, "this is a null object");
Preconditions.checkArgument(1 < 0, "this is a wrong answer.");
//陣列下標少於size
Preconditions.checkElementIndex(3, company.getCompanies().size());
}
}
Collection包:
ListsTest
package rich.collect;
import java.util.ArrayList;
import java.util.List;
import rich.model.Company;
import com.google.common.base.Function;
import com.google.common.collect.Lists;
public class ListsTest {
public static void main(String[] args) {
//分配一個arrayList 方法與
//List<Company> companies = new ArrayList<Company>();
//一樣
List<Company> companies = Lists.newArrayList();
//還可以指定初始大小
//List<Company> companies = Lists.newArrayListWithCapacity(10);
//List<Company> companies = Lists.newArrayListWithExpectedSize(20);
companies.add(Company.newCompany("oracle", "shenzhen"));
companies.add(Company.newCompany("tecent", "shenzhen"));
//建立LinkedList
List<Company> companies2 = Lists.newLinkedList();
//reverse list
List<Company> reverseCompanyList = Lists.reverse(companies);
//將list切分成大小為1的list陣列返回
List<List<Company>> partitionCompanyList = Lists.partition(companies, 1);
//複製一個list
List<Company> copyCompanyList = Lists.newCopyOnWriteArrayList(companies);
System.out.println();
//Arrays.asList()
String[] testList = {"acb","bdc"};
//可以繼續加單個object到list中,並對陣列進行list轉換
List<String> transformList = Lists.asList("dd", testList);
System.out.println(transformList.contains("dd"));
//transform方法配合function類使用
Function<Company, String> functionList = new Function<Company, String>() {
@Override
public String apply(Company company) {
return company.getName();
}
};
Lists.transform(companies, functionList);
//沒有filter方法
}
}
SetsTest
package rich.collect;
import java.util.Set;
import rich.model.Company;
import com.google.common.base.Predicate;
import com.google.common.collect.Sets;
public class SetsTest {
public static void main(String[] args) {
Company company = new Company();
company.init();
//Set 方法與list類似,只是物件集元素不重複
Set<Company> companySet = Sets.newHashSet();
companySet.addAll(company.getCompanies());
//newTreeSet,newLinkedHashSet()
Predicate<Company> predicate = new Predicate<Company>() {
@Override
public boolean apply(Company company) {
if(company.getName().equals("dell")) return false;
return true;
}
};
Set<Company> filterSet = Sets.filter(companySet, predicate);
System.out.println(filterSet.contains(company.getCompanies().get(1)));
}
}
MapsTest
package rich.collect;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import rich.model.Company;
import com.google.common.base.Function;
import com.google.common.base.Predicate;
import com.google.common.collect.Maps;
public class MapsTest {
public static void main(String[] args) {
Company company = new Company();
company.init();
List<Company> companies = company.getCompanies();
//Maps 建立一個map
Map<Company, String> companyMap = Maps.newHashMap();
//Map<Company, String> companyMapUtil = new HashMap<Company, String>();
companyMap.put(companies.get(0), "subsidiary");
companyMap.put(companies.get(1), "parentCompany");
//與Lists類似,可以建立expectedSize的
Map<Company, String> companyMap1 = Maps.newHashMapWithExpectedSize(10);
//也有newLinkHashMap,newTreeMap和newEnumMap
//同樣的,也可以使用Function和Predicate類進行轉換和過濾
//Function
Function<String, String> function = new Function<String, String>() {
@Override
public String apply(String relation) {
return relation + " is wrapped";
}
};
Map<Company, String> transformMap = Maps.transformValues(companyMap, function);
System.out.println(transformMap.containsValue("subsidiary is wrapped"));
//Predicate
Predicate<String> valuePredicate= new Predicate<String>() {
@Override
public boolean apply(String relation) {
if(relation.equals("UNKNOWN")) return false;
return true;
}
};
companyMap.put(Company.newCompany("oracle", "shenzhen"), "UNKNOWN");
Map<Company, String> filterValueMap = Maps.filterValues(companyMap, valuePredicate);
System.out.println(filterValueMap.containsValue("UNKNOWN"));
//除了value filter,還可以key filter,方法類似,不展開
}
}
IteralbesTest
package rich.collect;
import java.util.List;
import com.google.common.base.Predicate;
import com.google.common.collect.Iterables;
import com.google.common.collect.Lists;
import rich.model.Company;
public class IterablesTest {
public static void main(String[] args) {
//Iterables擴充套件iterable集合類方法
Company company = new Company();
company.init();
//concat方法,串聯list,set,vector等集合類
List<Company> newCompanyList = Lists.newArrayList();
newCompanyList.add(Company.newCompany("oracle", "shenzhen"));
newCompanyList.add(Company.newCompany("tecent", "shenzhen"));
Iterable iterablesList = Iterables.concat(newCompanyList, company.getCompanies());
//集合類方法,一般都會有function和Predicate方法。
//就是transform和filter方法,不展開
//但說一說find方法,find方法是找到第一個符合條件的value返回
Predicate<Company> predicate = new Predicate<Company>() {
@Override
public boolean apply(Company company) {
return company.getName() == "quest";
}
};
Company matchCompany = Iterables.find(iterablesList, predicate);
//因為如果找不到值的話,會報異常,所以一般會使用加defaultValue的find方法
Company matchCompany1 = Iterables.find(iterablesList, predicate, Company.newCompany("emc", "shanghai"));
if(matchCompany != null) {
System.out.println(matchCompany.getName());
}
//iterable是沒有size的方法,所以可以使用Iterables.size()方法
System.out.println(Iterables.size(iterablesList));
//還有就是getFirst和getLast方法,toArray方法,isEmpty方法等等,不展開
}
}
OrdingTest
package rich.collect;
import java.util.Arrays;
import java.util.Collections;
import java.util.Comparator;
import rich.model.Company;
import com.google.common.collect.ComparisonChain;
import com.google.common.collect.Ordering;
public class OrderingTest {
public static void main(String[] args) {
//Ordering類,實現Comparator介面
Ordering<Company> ordering = new Ordering<Company>() {
@Override
public int compare(Company company1, Company company2) {
return company1.getName().length() - company2.getName().length();
}
};
//使用compound方法,組合解決Comparator介面
Comparator<Company> comparator1 = new Comparator<Company>() {
@Override
public int compare(Company o1, Company o2) {
return o1.getLocation().length() - o1.getLocation().length();
}
};
Comparator<Company> comparator2 = new Comparator<Company>() {
@Override
public int compare(Company o1, Company o2) {
return o1.getName().length() - o1.getName().length();
}
};
Ordering<Company> ordering2 = Ordering.compound(Arrays.asList(comparator1, comparator2));
//進行排序
Company company = new Company();
company.init();
Collections.sort(company.getCompanies(), ordering2);
}
}
SpecificalMapTest有趣的方法都在這裡了,請詳閱
SpecificalMapTest
package rich.collect;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
import com.google.common.collect.HashBiMap;
import com.google.common.collect.HashMultimap;
import com.google.common.collect.HashMultiset;
import com.google.common.collect.Multimap;
import com.google.common.collect.Multiset;
public class SpecificalMapTest {
public static void main(String[] args) {
//Multiset 把重複元素的放入集合
//可以用於統計重複元素的數量
//例如有一個list裡面有各種字串,你要統計每個字串在list裡面出現的次數,偏向於一個bag的概念
List<String> wordList = getWordList();
// Map<String, Integer> map = new HashMap<String, Integer>();
// for(String word : wordList){
// Integer count = map.get(word);
// map.put(word, (count == null) ? 1 : count + 1);
// }
// Integer count = map.get("a");
//Multiset用法
Multiset<String> multiSet = HashMultiset.create();
multiSet.addAll(wordList);
int count = multiSet.count("a");
System.out.println(count + "--" + multiSet.size());
multiSet.setCount("a", 5);
System.out.println(multiSet.count("a") + "--" + multiSet.size());
//Multimap 在Map中value裡面放多個元素
//Map 的值像{k1=v1,k2=v2,...} Multimap像{k1=[v1,v2,v3],k2=[v4,v5],...}
//當然我們也可以這樣構建一個物件,這也是可以的,但顯得有些麻煩
HashMap<String, HashSet<String>> map = new HashMap<String, HashSet<String>>();
//Multimap用法,與上面等價
Multimap<String, String> hashMultimap = HashMultimap.create(); //HashSet不能儲存相同value元素,繼承SetMultimap
hashMultimap.put("dell", "zhuhai");
hashMultimap.put("dell", "shanghai");
hashMultimap.put("dell", "shanghai");
Collection<String> mapCollection = hashMultimap.get("dell");
Iterator c = mapCollection.iterator();
while(c.hasNext()) {
System.out.println(c.next());
}
//除了HashMultimap,還有ArrayListMultimap,LinkedHashMultimap,TreeMultimap,ImmutableMultimap 不展開
//BiMap value和key都不能重複 可以根據value推斷key值
//也可以key和value互換
HashBiMap<String, String> biMap = HashBiMap.create();
biMap.inverse();
//RangeMap
}
public static List<String> getWordList() {
List<String> wordList = new ArrayList<String>();
wordList.add("a");
wordList.add("ab");
wordList.add("ab");
wordList.add("a");
wordList.add("a");
wordList.add("c");
return wordList;
}
}
Primitive包
PrimitivesTest
package rich.primitive;
import java.util.Collections;
import java.util.List;
import com.google.common.collect.Lists;
import com.google.common.primitives.Doubles;
public class PrimitivesTest {
public static void main(String[] args) {
//Double,float,int,boolean等等
//Double.valueOf("12.2bb");
Double.parseDouble("");
//用這種方法的主要原因是因為錯誤的時候不會丟擲exception,如果錯誤的時候返回的是null值
Doubles.tryParse("12.0bb");
double[] abc = {12.0,52.1};
Doubles.max(abc);
Doubles.min(abc);
//當然你也可以使用Collection的max和min方法。不用重寫comparator
List<Integer> testCollection = Lists.newArrayList();
testCollection.add(2);
testCollection.add(1);
testCollection.add(3);
System.out.println(Collections.max(testCollection));
//陣列是否有12.0這個值
Doubles.contains(abc, 12.0);
//陣列和集合的轉換
//asList和toArray方法
//indexOf和lastIndexOf方法
}
}
guava中文 api(不全)
the latest version: guava-18.0.jar about guava api