Jakarta Commons Cookbook读书笔记--Commons Collections(函子篇)
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"
按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进行排序
先加入的Comparator拥有较高优先级。上面例子中20岁的Auther会排在18岁的Ben前面,而相同的名字则年轻的会排在前面。
3.1.3 使用NullComparator包装Comparator,控制对null的排序
3.1.4 使用FixedOrderComparator执行固定顺序的排序
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过滤重复的对象。
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(),其设计的目的就是进行对象的转换,接受一个对象并据此创建一个新对象。
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实现转换链
3.3.2 结合Predicate和Transformer实现有条件的转换
3.4 模拟闭包的接口Closure
3.4.1 实现一个给商品价格打9折的Closure
3.4.2 使用ChainedClosure链接多个Closure
3.4.3 使用IfClosure模拟条件语句
因为IfClosure构造函数接受Closure作为参数,所以IfClosure还可以嵌入其他IfClosure
3.4.4 使用WhileClosure,ForClosure模拟循环语句
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);
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 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 );
// 第二个参数为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;
...
}
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);
// 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
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);
}
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);
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);
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);
}
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 );
}
}
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);
// 对商品打九折,打包好后送达客户
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);
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);
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读书笔记系列
程序员的一生其实可短暂了,这电脑一开一关,一天过去了,嚎;电脑一开不关,那就成服务器了,嚎……