Jakarta Commons Cookbook讀書筆記系列
3 Commons Collections v3.0
功能說明:增強java的泛型框架,引入函子的概念
主要功能:增加了一些函子的接口以及一些實現。包括一些實現了Comparator的類,封裝了條件和判別式的Predicate接口,實現對象轉換的Transformer接口以及模擬閉包的接口Closure;另外還有對jdk泛型框架的擴展。
概念介紹:
函子(functor):執行操作或功能的部件。例如java.util.Comparator和java.util.Iterator。他們都用于隔離算法。
此次文章篇幅較長,讀者可以選擇著重閱讀斜體和著色文字,代碼部分可以選擇閱讀。
3.1 Comparator的擴展
3.1.1 使用ReverseComparator實現反順序排列。
排序前
Book book
|--List authors
|--[0]->Person person1
|--String name->"LiLei"
|--[1]->Person person2
|--String name->"Ark"
|--[2]->Person person3
|--String name->"HanMeimei"
import org.apache.commons.collections.comparators.ReverseComparator;
Comparator nameComparor=new org.apache.commons.beanutils.BeanComparator("name");
Comparator reverseComparator=new ReverseComparator(nameComparor);
Collections.sort(book.getAuthors(),reverseComparator);
按name屬性反向排序后
Book book
|--List authors
|--[0]->Person person1
|--String name->"LiLei"
|--[1]->Person person2
|--String name->"HanMeimei"
|--[2]->Person person3
|--String name->"Ark"
通常情況下,如果只有一個Comparator。ReverseComparator顯得有些雞肋,因為可以通過Arrays.reverse()和Collections.reverse()將數組或者List反轉。但是如果有多個Comparator,它的意義就顯現出來了。
3.1.2 ComparatorChain結合多個Comparator進行排序
import org.apache.commons.collections.comparators.ComparatorChain;
Comparator nameComparor=new org.apache.commons.beanutils.BeanComparator("name");
Comparator ageComparator=new org.apache.commons.beanutils.BeanComparator("age");
ComparatorChain comparatorChain=new ComparatorChain();
comparatorChain.addComparator(nameComparor);
comparatorChain.addComparator(ageComparator);
Collections.sort(book.getAuthors(),comparatorChain);
先加入的Comparator擁有較高優先級。上面例子中20歲的Auther會排在18歲的Ben前面,而相同的名字則年輕的會排在前面。
3.1.3 使用NullComparator包裝Comparator,控制對null的排序
import org.apache.commmons.collections.comparators.NullComparator;
//第二個參數為false,則name屬性為null的值排在非null的前面;如果為true,則反之。如果不加第二個參數,則默認為true;
Comparator nullComparator =new NullComparator(nameComparator,false);
3.1.4 使用FixedOrderComparator執行固定順序的排序
public class PokerCard{
private String value;
private String suit;
...
}
import org.apache.commons.collections.comparators.FixedOrderComparator
//52張撲克牌從小到大排序例子
String[] suitOrder=new String{"Diamond","Club","Heart","Spade"};
String[] valueOrder=new String{"2","3","4","5","6","7","8","9","10","J","Q","K","A"}
Comparator suitComparator=new FixedOrderComparator(suitOrder);
suitComparator=new BeanComparator("suit",suitComparator);
Comparator valueComparator=new FixedOrderComparator(valueOrder);
valueComparator=new BeanComparator("value",valueComparator);
Comparator comparatorChain=new ComparatorChain();
comparatorChain.add(suitComparator);
comparatorChain.add(valueComparator);
Collections.sort(pokerCardList,comparatorChain);
3.2 使用Predicates封裝條件或者判別式
以下所有的類都繼承org.apache.commons.collections.Predicate接口,而且該接口只有一個方法evaluate(Object)
package org.apache.commons.collections;
public interface Predicate {
public boolean evaluate(Object object);
}
EqualsPredicate 相當于調用Equals對比
IdentityPredicate 相當于==操作符
NotPredicate 裝飾給定的Predicate并返回相反的值
InstanceOfPredicate 相當于instanceof
NullPredicate 當對象為null時返回true
NullIsTruePredicate 裝飾給定的Predicate,如果對象為null則返回true,否則返回給定Predicate的判定值
NotNullPredicate 當對象不為null時返回true
NullIsFalsePredicate 裝飾給定的Predicate,如果對象為null則返回false,否則返回給定Predicate的判定值
TruePredicate 總是返回true
FalsePredicate 總是返回false
UniquePredicate 首次evaluate判定對象總是返回true。其內部維護一個HashSet,每次調用evaluate(obj),將會調用HashSet的add方法。該類常用于Collections過濾重復的對象。
import org.apache.commons.collections.Predicate;
Predicate isHeis=new EqualsPredicate("Heis");
Predicate notHeis=new NotPredicate(isHeis);
Predicate nullIsTruePredicate=new NullIsTruePredicate(isHeis);
Predicate instanceOfPredicate =new InstanceOfPredicate(String.class);
isHeis.evaluate("Heis");->true
notHeis.evaluate("His");->true
nullIsTruePredicate.evaluate(null);->true
nullIsTruePredicate.evaluate("Heis");->true
instanceOfPredicate.evaluate("Heis");->true
3.2.1 復合Predicate實現復雜的條件邏輯
AndPredicate and關系
OrPredicate or關系
AllPredicate 條件之間為and關系
OnePredicate 當只有一個條件為true時,返回true
AnyPredicate 條件之間為or關系
Predicate isHeis=new EqualsPredicate("Heis");
Predicate isNotNull=NotNullPredicate.INSTANCE;
Predicate isMale=new EqualsPredicate("male");
Predicate andPredicate=new AndPredicate(isHeis,isNotNull);
Predicate orPredicate=new OrPredicate(isHeis,isNotNull);
Predicate[] predicates=new Predicate[]{isHeis,isNotNull,isMale};
Predicate allPredicate=new AllPredicate(predicates);
Predicate onePredicate=new OnePredicate(predicates);
3.3 利用Transformer實現對象轉換
Transformer接口只有一個方法transform(),其設計的目的就是進行對象的轉換,接受一個對象并據此創建一個新對象。
package org.apache.commons.collections;
public interface Transformer {
public Object transform(Object input);
}
import org.apache.commons.collections.Transformer;
//大黃蜂變形器
Transformer BumblebeeTrans=new Transform(){
public Object transform(Object input){
if(input instanceof BumblebeeRobot){
return new BumblebeeCar(input);
}else{

}
}
}
//大黃蜂機器人模式轉換為汽車模式
BumblebeeCar car=BumblebeeTrans.transform(BumblebeeRobot.getInstance());
3.3.1 使用ChainedTransformer實現轉換鏈
import org.apache.commons.collections.functors.ChainedTransformer;
Transformer[] chainElements=new Transformer[]{transformer1,transformer2};
Transformer chain=new ChainedTransformer(chainElements);
Object transformedResult=chain.transform(input);
3.3.2 結合Predicate和Transformer實現有條件的轉換
import org.apache.commons.collections.functors.SwitchTransformer;
Transformer defaultTransformer;
Transformer[] tArray=new Transformer[]{t1,t2};
Predicate[] pArray=new Predicate[]{p1,p2};
Transformer st=new SwitchTransformer(tArray,pArray,defaultTransformer);
//如果p1為true,則執行t1;如果p2為true,則執行t2;否則執行defaultTransformer
Object tranformedResult=st.transform(input);
3.4 模擬閉包的接口Closure
package org.apache.commons.collections;
public interface Closure {
public void execute(Object input);
}
3.4.1 實現一個給商品價格打9折的Closure
Closure discountClosure=new Closure(){
public void execute(Object input){
Product p=(Product)input;
p.setPrice(p.getPrice()*0.9);
}
}
3.4.2 使用ChainedClosure鏈接多個Closure
import org.apache.commons.collections.functors.ChainedClosure;
//對商品打九折,打包好后送達客戶
Closure cArray=new Closure[]{discountClosure,packageClosure,postClosure};
Closure process=new ChainedClosure(cArray);
process.execute(product);
3.4.3 使用IfClosure模擬條件語句
import org.apache.commons.collections.functors.IfClosure;
Predicate isDiscountProduct=new Predicate(){
public boolean evaluate(Object object){
Product p=(Product)input;
return p.isDiscountProduct();
}
}
//如果是折扣商品則打折出售(執行discountClosure.execute()),否則原價出售(執行noDiscountClosure.execute())。
Closure discountAction=new IfColsure(isDiscountProduct,discountClosure,noDiscountClosure);
discountAction.execute(product);
因為IfClosure構造函數接受Closure作為參數,所以IfClosure還可以嵌入其他IfClosure
3.4.4 使用WhileClosure,ForClosure模擬循環語句
//判斷是否庫存過多
Predicate isSurplus=new Predicate(){
public boolean evaluate(Object object){
Product p=(Product)input;
return p.isSurplus();
}
}
//如果庫存過多,繼續打折,直至庫存不在富余
Closure getItCheap=new WhileClosure(isSurplus,discountClosure);
getItCheap.execute(product);
//對商品進行3次打折
Closure getItCheap=new ForClosure(3,discountClosure);
getItCheap.execute(product);
Jakarta Commons Cookbook讀書筆記系列
程序員的一生其實可短暫了,這電腦一開一關,一天過去了,嚎;電腦一開不關,那就成服務器了,嚎……