apache commons collections

apache commons collections

 
本文简要的介绍了apache commons中的collections框架内容。 commons collections
java集合框架是jdk 1.3对jdk1.2的一个主要的补充。java集合框架包含了很多强大的数据结构,这些数据结构加快了很多重要的java程序的开发。从那之后,集合框架就已经成为java处理集合的公开标准。
commons-collections以jdk的集合框架为基础,提供了新的接口、实现以及工具。它具有以下特点:
® bag接口:适用于包含一个对象的多个拷贝的集合
® buffer接口:适用于具有顺序的集合类,例如fifos(先进先出)
® bidimap(双向映射):可以通过值查找键,也可以通过键查找值
® map迭代器:提供了对映射的快速迭代
® 对类型检查进行了封装,确保特定类的实例可以被添加到集合中
® 对转换进行了封装,将集合中的对象转换成被加入时的类型
® 对集合进行组合,使多个集合看起来就像一个集合一样
® 有序映射和set,保持元素添加时的顺序,包括一个基于lru的map
® 标识映射可以给予对象的==来比较对象,而不是基于equals方法
® 引用映射可以允许键and/or值可以有控制的进行回收
® 很多比较器的实现
® 很多迭代器的实现
® 从数组或者枚举到集合的适配器
® 用来测试或者创建典型set理论的集合属性,例如与、或、闭包
用户指南:
commons-collections为了帮助日复一日的编程,提供了大量的类。本部分主要介绍了一些collections的关键特性。
注意同步
commons-collections使用了和标准java集合类似的同步设计方法。如果不添加额外的同步方法,大多数关于集合、映射和bag的实现都不是线程安全的。集合的synchronizexxx方法就是这些实现中的一种方式,可以使集合在多线程的应用程序中被同步。
类层次的javadoc应该指出如果没有额外的同步机制,在进行多线程访问时,某个特定的实现是否是安全的。如果没有特别指出是线程安全的,那么就被认为是需要进行同步的。
工具类:
每个主要的集合接口都有一个utility类。因此,set和sortedset接口的utility类就是setutils。这些utility类提供了操作集合类型的共通方法。
基本的方法都包含在两个根集合接口的utility类中,即collectionutils和maputils。因为所有的其他集合接口都集成collection或者map,所以collectionutils和maputils可以被扩展使用。共同的方法包括交集操作、计数操作、迭代操作、逻辑操作和类型强制转换操作等。同时,utility类还提供了对集合封装类的访问,这与jdk collections类的方式类似。
maps
map 迭代
jdk中的map接口很难进行迭代。api用户总是需要通过entryset或者keyset进行迭代。commons-collectons现在提供了一个新的接口—mapiterator来允许对maps进行简单的迭代。
iterablemap map = new hashmap();
mapiterator it = map.mapiterator();
while(it.hasnext()){
object key = it.next();
object value = it.getvalue();
it.setvalue(newvalue);
}
有序 map
commons-collections为maps提供了一个新的接口,orderedmap,这个接口是有顺序的,但是并没有进行排序。linkedmap和listorderedmap(封装器)是这个接口的两种实现。这个接口支持map迭代,同时允许对map进行前向迭代和反向迭代。
orderedmap map = new hashmap();
map.put(“five”,5);
map.put(“six”,6);
map.put(“seven”,7);
map.firstkey();       //returns “five”
map.nextkey(“five”);   //returns “six”
map.nextkey(“six”);     //returns “seven”
biddirectional maps 双向映射
commons-collections提供了新的接口层次,用于支持双向的映射,即bidimap接口。可以通过key来查找value,也可以通过value来查找key。
bidimap bidi = new treebidimap();
bidi.put(“six”,”6”);
bidi.get(“six”);      //returns “6”
bidi.getkey(“6”);    //returns “six”
bidi.removevalue(“6”);  //removes the mapping
bidimap inverse = bidi.inversebidimap();  //returns a map with keys and values swapped
对于有序的和排序的双向map,也公共了对应的接口。对于每种双向map类型都提供了接口的实现。
queues&buffers 队列和缓冲
buffer接口用来支持队列和缓冲。这些接口表示集合可以定义删除的顺序。
buffer buffer = new unboundedfifobuffer();
buffer.add(“one”);
buffer.add(“two”);
buffer.add(“three”);
buffer.remove();   //removes and returns the next in order,”one” as this is a fifo
buffer.remove();   //removes and returns the next in order,”two” as this is a fifo
fifo(队列)、lifo(堆栈)和priority(根据比较器的顺序)的接口实现已经被提供。
bags
bag接口用于支持bag。它用于表示包含了一个对象的多个拷贝的结合。
bag bag = new hashbag();
bag.add(“one”,6); //add 6 copies of “one”
bag.remove(“one”,2);  //removes 2 copies of “one”
bag.getcount(“one”);  //returns 4
对于排序和为排序的bag,具有对应的接口实现。
 
下面是对internet中一篇文章的翻译,原文出处:http://www.devx.com/java/article/29392/0/page/3
jdk中不是已经有了java集合框架了吗,为什么还要使用apache的集合呢?这是因为apache的集合时对jdk集合的一个补充和增强,它提供了更多的接口和实现类。甚至于它应该成为jdk的一部分。
下面是一些笔者比较喜欢的特性:
® bag接口
® 固定大小的map、lru (最近最少使用算法)map和双重(dual)map
® 对象数组和map的迭代器
® map的multikey
® 大量的工具类,提供了使用api的快捷方式
® 封装器,对大多数类提供了自定义的方法
collections类根据下面列举的包结构进行组织:
org.apache.commons.collections
org.apache.commons.collections.bag
org.apache.commons.collections.bidimap
org.apache.commons.collections.buffer
org.apache.commons.collections.collection
org.apache.commons.collections.comparators
org.apache.commons.collections.functors
org.apache.commons.collections.iterators
org.apache.commons.collections.keyvalue
org.apache.commons.collections.list
org.apache.commons.collections.map
org.apache.commons.collections.set
 
org.apache.commons.collections
这个包中定义了由其他包实现的接口、作为工厂类(可以实例化集合类或者集合的封装类)的共通类。一些比较重要的类有arraystack、beanmap、extendedproperties、fastarraylist、fasthashmap和fasttreemap。这些类的细节包含在javadoc中,下面只是简要的介绍各个类在实际中的应用:
arraystack:arraystack类实现了stack接口,基于arraylist用来在单线程环境中使用。例如,如果想在一个方法中使用stack进行一些处理,这个类在性能上会比stack(jdk1.4.2中使用vector)好一些。
beanmap:就像swing gui中的jbutton一样,使用beanmap,甚至可以将一个map作为一个javabean来进行处理。当在设计用来显示数据源或者应用程序配置属性的gui时,map可以在屏幕上被拖放(d&d)。
extendedproperties:这是一个非常有用的类。它和java.util.properties类似,包含了一个用于加载配置信息的load方法,但是这个类有以下的好处:
# 属性值可以分布在多行
# 提供了用于获取非字符串值的方法。例如,getfload方法用于获取一个fload类型的值。这样就不需要使用wrapper方法来转换获取的字符串值了。
fastarraylist, fasthashmap, fasttreemap:这些类可以在多线程环境中使用,如果存在很多只读操作的话。这些类是分别基于arraylist、hashmap和treemap的。
org.apache.commons.collections.bag
如果需要将一个对象的多个拷贝添加到一个list中时,这个包下面的类就变得非常有用了。在这种情况下,很多开发人员会将对象添加到一个arraylist中,然后每天加一次都要进行一下迭代,来判断是否添加了给定类型的对象。在线购物车是这种情况的一个实际的需求。这种方法的缺点是内存和速度上的不足。
解决上述需求的一个比较好的设计就是只保存一个对象的拷贝,而在添加同样类型的实体时,只是增加计数器的值。hashbag和treebag类(分别基于hashmap和treemap)很好的满足了这个需求。
如下面的例子所示:
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
 */
public interface 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
 */
public class 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类都比较有用。

你可能感兴趣的:(apache commons collections)