如下面的例子所示:
package in.co.narayanan.commons.collections.bag;
import junit.framework.TestCase;
import org.apache.commons.collections.Bag;
import org.apache.commons.collections.bag.HashBag;
/**
* This domain represents an order placed by the customer.
*
* @author Narayanan A R
*/
public class Order {
private Bag orderedProducts;
public Order() {
orderedProducts = new HashBag();
}
public void addProduct(Product p) {
orderedProducts.add(p);
}
public int countWindowsLicenses() {
return orderedProducts.getCount(Product.WINDOWS);
}
public int countLinuxLicenses() {
return orderedProducts.getCount(Product.LINUX);
}
}
class Product {
//OsType is an enum
public static final Product WINDOWS = new Product(OsType.WINDOWS);
public static final Product LINUX = new Product(OsType.LINUX);
public static final Product MAC = new Product(OsType.MAC);
public static final Product HPUNIX = new Product(OsType.HPUNIX);
private int quantity;
private int version;
private float prize;
private OsType type;
public Product(OsType type) {
this.type = type;
}
public int getQuantity() {
return quantity;
}
public void setQuantity(int quantity) {
this.quantity = quantity;
}
public int getVersion() {
return version;
}
public void setVersion(int version) {
this.version = version;
}
public float getPrize() {
return prize;
}
public void setPrize(float prize) {
this.prize = prize;
}
public OsType getType() {
return type;
}
public void setType(OsType type) {
this.type = type;
}
@Override
public boolean equals(Object o) {
if (o instanceof Product) {
return ((Product) o).getType().equals(this.getType());
}
return super.equals(o);
}
@Override
public int hashCode() {
return type.hashCode();
}
@Override
public String toString() {
return type.toString();
}
}
class TestOrder extends TestCase {
public void testOrder() {
Order order = new Order();
order.addProduct(new Product(OsType.WINDOWS));
order.addProduct(new Product(OsType.WINDOWS));
order.addProduct(new Product(OsType.WINDOWS));
order.addProduct(new Product(OsType.LINUX));
order.addProduct(new Product(OsType.LINUX));
order.addProduct(new Product(OsType.HPUNIX));
order.addProduct(new Product(OsType.MAC));
int licenses;
licenses = order.countWindowsLicenses();
assertEquals(3, licenses);
licenses = order.countLinuxLicenses();
assertEquals(2, licenses);
}
}
通过调试,运行到上述红色行时,order的成员变量orderedProducts的内容为:(toString显示内容)
[2:LINUX,1:MAC,1:HPUNIX,3:WINDOWS]
即实际上只存储了一个对象的拷贝,然后使用数字进行标识个数。
而orderedProducts的成员HashMap对象的size为4。
org.apache.commons.collections.bidimap
很多Java开发人员通过使用两个HashMap来获取一个键值,方法是将一个值作为键传递到另外一个HashMap。正常情况下,需要对同等的处理名字和值,在这种情况下,就是值也可以做为键(因为在map中键是唯一的,而值是可以不唯一的)。
关于org.apache.commons.collections.bidimap的例子是一个原型适配器,集成了PeopleSoft和Siebel命令行处理引擎,假定一个引擎中的每个命令在另外一个中都有同样的对应。可以在in.co.narayanan.commons.collections.bidimap中找到相关的类。可以通过SiebelPeopleSoftConnector来了解这些类,SiebelPeopleSoftConnector作为适配器,并包含了BidiMap对象。当收到处理Siebel命令的请求后,就从BidiMap获取对应的PeopleSoft命令,然后传送给PeopleSoft命令引擎。反之亦然。样例代码中只包含应用程序的一个轮廓。
/**
*Definescontractforthesystemstoconsumeagiven
*command.
*
*@authorNarayananAR
*/
publicinterface ICommandConsumer {
Object consume(String command, Object arg);
}
class SiebelCommandConsumer implements ICommandConsumer {
public Object consume(String command, Object arg) {
System.out.println("Processing Siebel command:" + command);
System.out.println("Arg:" + arg);
return"SIEBEL:" + command + "-SUCCESSFUL";
}
}
class PeopleSoftCommandConsumer implements ICommandConsumer {
public Object consume(String command, Object arg) {
System.out.println("Processing PeopleSoft command:" + command);
System.out.println("Arg:" + arg);
return"PEOPLESOFT:" + command + "-SUCCESSFUL";
}
}
import org.apache.commons.collections.bidimap.TreeBidiMap;
import org.apache.commons.collections.BidiMap;
/**
*Responsibleforadaptingboththesystem'scommands.
*
*@authorNarayananAR
*/
publicclass SiebelPeopleSoftConnector {
private ICommandConsumer peopleSoft;
private ICommandConsumer siebel;
private BidiMap commandMap;
public SiebelPeopleSoftConnector(ICommandConsumer peopleSoft,
ICommandConsumer siebel) {
this.peopleSoft = peopleSoft;
this.siebel = siebel;
commandMap = prepareCommandMapping();
}
private BidiMap prepareCommandMapping() {
BidiMap map = new TreeBidiMap();
map.put("start", "init");
map.put("exit", "quit");
map.put("delete", "remove");
return map;
}
/**
*DelegatesthecalltothePeopleSoftcommandenginebyfetchingthemappedcommand.
*
*@paramcommandSiebelcommand
*@paramargArgumentifany
*@returnResultreturnedfromPeopleSoftcommandengine
*/
public Object processSiebelCommand(String command, Object arg) {
returnpeopleSoft.consume((String)commandMap.get(command), arg);
}
/**
*DelegatesthecalltotheSiebelcommandenginebyfetchingthemappedcommand.
*
*@paramcommandPeopleSoftcommand
*@paramargArgumentifany
*@returnResultreturnedfromSiebelcommandengine
*/
public Object processPeopleSoftCommand(String command, Object arg) {
returnsiebel.consume((String)commandMap.getKey(command), arg);
}
}
即可以根据key查找value,也可以根据value查找key。
org.apache.commons.collections.buffer
这个包中包含了封装类,直接实现了java.util.Collection接口。因此,任何实现Collection接口的类都可以使用这些封装类。比较常用的类有PredicatedCollection、CompositeCollection、SynchronizedCollection、TransformedCollection、TypedCollection和UnmodifiableCollection。下表提供了关于这些类的一个概览:
PredicatedCollection:可以通过使用这个类的实例来追加限制条件,将条件定义成一个独立的对象,也就是所谓的前提条件,然后作为参数传送给封装类的工厂方法。
▶ CompositeCollection:使用这个类可以创建集合的集合,并且当添加或者删除对象时具有一个统一的视图。
▶ SynchronizedCollection:可以使既存的集合线程安全。
▶ TransformedCollection:当将对象添加到集合时转换对象的类型。例如由String-->Integer。
▶ TypedCollection:与Java 1.5类似的泛型。
▶ UnmodifiableCollection:使集合的引用不可以被修改。
org.apache.commons.collections.comparators
这个包中包含了很多可复用的类。NullComparator类和FixedOrderComparator是最常用的类。
NullComparator:当对数组或者列表中的实体进行排序时,将null实体移到底部。
FixedOrderComparator:将一个集合中的顺序重新保存在预定义的列表中。
org.apache.commons.collections.functors
org.apache.commons.collections.iterators
在这个包中包含了很多实现了java.util.Iterator接口的类。比较重要的类有MapIterator、ArrayIterator、CollatingIterator、LoopingIterator和IteratorUtils。需要通过使用IteratorUtils类来使用这个包中的类。
org.apache.commons.collections.keyvalue
这个包中的MultiKey类非常有用。如果想要在应用程序中创建一个域(domain)对象并将它们存储在一个基于联合逐渐的map中,就可以通过创建一个MultiKey的实例,使用记录的主键的值作为参数。然后将这个实例传递给map来存储域对象。
这个包中的类的其他用途是存储locale相关的实体,在这种情况下,实际的主键和locale name联合组成key。
org.apache.commons.collections.list
TreeList、FixedSizeList、NodeCachingLinkedList、CursorableLinkedList、TransformedList和PredicatedList类都是这个包中比较重要的类。它们的javadoc也非常清楚的描述了各自的功能。
org.apache.commons.collections.map
CaseInsensitiveMap、CompositeMap、FixedSizeMap、Flat3Map、LazyMap、LinkedMap、LRUMap、MultiKeyMap、PredicatedMap、SingletonMap和StaticBucketMap类都比较有用。