Jakarta Commons Cookbook读书笔记--Commons Collections(容器篇之一)
Jakarta Commons Cookbook读书笔记系列
3.5 Iterator的扩展
3.5.1 循环迭代器LoopingIterator
List books = new ArrayList();
books.add( " EnglishBook " );
books.add( " Commons Cookbook " );
books.add( " Who Moved My Cheese " );
// 当迭代到最后的元素后,再返回第一个元素重新循环,直至达到迭代次数为止
LoopingIterator iterator = new LoopingIterator(books);
for ( int i = 0 ;i < 5 ;i ++ ){
String book = (String)iterator.next();
System.out.print(book + " ; " );
}
-> EnglishBook;Commons Cookbook;Who Moved My Cheese;EnglishBook;Commons Cookbook;
3.5.2 ArrayList迭代器ArrayListIterator
可以自定义范围地遍历
String[] arrays = new String[]{ " a " , " b " , " c " , " d " , " f " };
// 遍历下标为1到4的元素
Iterator iterator = new ArrayListIterator(arrays, 1 , 4 );
while (iterator.hasNext()){
System.out.print(iterator.next() + " ; " );
}
-> b; c; d;
3.5.3 筛选迭代器FilterIterator
使用Predicate筛选,关于Predicate的介绍,请看我的这系列的上一篇文章Jakarta Commons Cookbook读书笔记--Commons Collections(函子篇)
import org.apache.commons.collections.Predicate;
List list = new ArrayList(Arrays.asList( new Integer[]{ 7 , 9 , 35 , 67 , 88 }));
// 过滤出大于30的元素
Predicate predicate = new Predicate(){
public boolean evaluate(Object object){
int num = ((Integer)object).intValue();
return num > 30 ;
}
};
Iterator iterator = new FilterIterator(list.iterator(),predicate);
while (iterator.hasNext()){
System.out.print(iterator.next() + " ; " );
}
-> 35 ; 67 ; 88 ;
3.5.4 过滤重复的元素UniqueFilterIterator
Iterator iterator = new UniqueFilterIterator(list.iterator());
while (iterator.hasNext()){
System.out.print(iterator.next() + " ; " );
}
-> a; b; c;
3.6 使用Bag
Bag是这样的一种容器,它能够存储多个逻辑相等(即equals()为true,而且hash()相等)的元素,并可以统计它们的个数。
3.6.1 高性能的HashBag
Bag bag1 = new HashBag();
bag1.add( " book1 " , 10 );
bag1.add( " book2 " , 20 );
Bag bag2 = new HashBag();
bag2.add( " book2 " , 5 );
bag2.add( " book3 " , 10 );
bag1.add( " book1 " );
bag1.remove( " book1 " , 2 );
// 减去bag2内相应元素的数量
bag1.removeAll(bag2);
System.out.println( " book1: " + bag1.getCount( " book1 " ));
System.out.println( " book2: " + bag1.getCount( " book2 " ) + " \n " );
// bag1保留bag2内的元素,简单来说就是求交集
bag1.retainAll(bag2);
System.out.println( " book1: " + bag1.getCount( " book1 " ));
System.out.println( " book2: " + bag1.getCount( " book2 " ));
System.out.println( " book3: " + bag1.getCount( " book3 " ));
->
book1: 9
book2: 15
book1: 0
book2: 5
book3: 0
3.6.2 TreeBag可以保存加入元素的顺序
Bag bag1 = new TreeBag();
bag1.add( " book1 " , 2 );
bag1.add( " book2 " , 1 );
bag1.add( " book3 " , 2 );
bag1.add( " book4 " , 1 );
bag1.add( " book5 " , 1 );
Iterator iterator = bag1.iterator();
while (iterator.hasNext()){
System.out.println(iterator.next());
}
->
book1
book1
book2
book3
book3
book4
book5
HashBag内部原理是使用一个HashMap当作内部容器,key为加入的对象,对应的value是对象的次数。同理TreeBag使用TreeMap作为内部容器。
需 要注意的是虽然Bag继承了Collection,但是它的removeAll(),containsAll(),add(),remove()和 retainAll()方法并不严格遵循Collection接口的规范。例如removeAll方法根据规范是移除所有的元素,而Bag的 removeAll是带参数的,只移除参数包含的元素。
3.7 用于临时数据转移的Buffer
Buffer类似于java5.0中的Queue,是个先进先出(First-in First-out)的数据容器。
3.7.1 无尺寸缓冲区UnboundFifoBuffer和有尺寸缓冲区BoundedFifoBuffer
Buffer bBuffer = new BoundedFifoBuffer( 2 );
bBuffer.add( " book1 " );
bBuffer.add( " book2 " );
try {
bBuffer.add( " book3 " );
} catch (BufferOverflowException e){
System.out.println( " Buffer is over flow " );
}
// 移除第一个加入的元素
bBuffer.remove();
Iterator iterator = bBuffer.iterator();
while (iterator.hasNext()){
System.out.println(iterator.next());
}
->
Buffer is over flow
book2
Buffer bBuffer = new UnboundedFifoBuffer( 2 );
bBuffer.add( " book1 " );
bBuffer.add( " book2 " );
try {
bBuffer.add( " book3 " );
} catch (BufferOverflowException e){
System.out.println( " Buffer is over flow " );
}
// 移除第一个加入的元素
bBuffer.remove();
Iterator iterator = bBuffer.iterator();
while (iterator.hasNext()){
System.out.println(iterator.next());
}
->
book2
book3
3.7.2 带优先级的缓冲区PriorityBuffer
按照数值从小到大排列
Buffer pBuffer = new PriorityBuffer();
pBuffer.add( new Long( 2 ));
pBuffer.add( new Long( 20 ));
pBuffer.add( new Long( 12 ));
pBuffer.add( new Long( 4 ));
Iterator iterator = pBuffer.iterator();
while (iterator.hasNext()){
System.out.println(iterator.next());
}
->
2
4
12
20
PriorityBuffer允许使用Comparator来排列优先顺序,关于Comparator,请看我的这系列的上一篇文章Jakarta Commons Cookbook读书笔记--Commons Collections(函子篇)
// 按照销售数量从大到小排列
public class RecommandComparator implements Comparator {
public int compare(Object o1, Object o2) {
int result =- 1 ;
if (o1 instanceof Book && o2 instanceof Book){
Book book1 = (Book)o1;
Book book2 = (Book)o2;
result = book1.getSalsNum().compareTo(book2.getSalsNum());
}
return result;
}
}
import org.apache.commons.collections.buffer.PriorityBuffer;
Buffer pBuffer = new PriorityBuffer( new ReverseComparator( new RecommandComparator()));
pBuffer.add( new Book( " book1 " ,Long.valueOf( 200 )));
pBuffer.add( new Book( " book2 " ,Long.valueOf( 7200 )));
pBuffer.add( new Book( " book3 " ,Long.valueOf( 163 )));
pBuffer.add( new Book( " book4 " ,Long.valueOf( 569 )));
Iterator iterator = pBuffer.iterator();
while (iterator.hasNext()){
Book book = (Book)iterator.next();
System.out.println(book.getName() + " : " + book.getSalsNum());
}
->
book2: 7200
book4: 569
book3: 163
book1: 200
3.7.3 使用阻塞式缓冲区BlockingBuffer
BlokingBuffer装饰一个Buffer实例,并使其处于阻塞状态,只要有对象加入则马上处理。当一个进程调用以BlockingBuffer的get()和remove()方法时,将不返回任何值,直到它有一个对象返回。
public class BufferListener implements Runnable{
private Buffer buffer;
public BufferListener(Buffer buffer){
this .buffer = buffer;
}
public void run() {
while ( true ){
String msg = (String)buffer.remove();
System.out.println(msg);
}
}
}
Buffer buffer = BlockingBuffer.decorate( new UnboundedFifoBuffer());
BufferListener listener = new BufferListener(buffer);
Thread listenerThread = new Thread(listener);
listenerThread.start();
buffer.add( " book1 " );
buffer.add( " book2 " );
->
book1
book2
3.8 Map的扩展
3.8.1 使用MultiMap实现一键存储多个值
MultiValueMap会使用一个ArrayList来保存同一个键的所有值
import org.apache.commons.collections.map.MultiValueMap;
MultiMap map = new MultiValueMap();
map.put( " key " , " value1 " );
map.put( " key " , " value2 " );
map.put( " key " , " value2 " );
System.out.println((Collection)map.get( " key " ));
-> [value1, value2, value2]
3.8.2 使用BidiMap实现根据值检索键
DualHashBidiMap使用两个HashMap来保存键值对,其中一个正常保存键值对,另一个反过来保存值对应的键。
import org.apache.commons.collections.bidimap.DualHashBidiMap;
BidiMap map = new DualHashBidiMap();
map.put( " key1 " , " value " );
System.out.println(map.get( " key1 " ));
System.out.println(map.inverseBidiMap().get( " value " ));
->
value
key1
DualTreeBidiMap是可以记住加入顺序的BidiMap,其内部使用TreeMap来保存键值对。
3.8.3 大小写不敏感的CaseInsensitiveMap
CaseInsensitiveMap map = new CaseInsensitiveMap();
map.put( " KEY " , " value " );.
map.put( " key " , " value2 " );
System.out.println(map.get( " key " ));
-> value2
3.8.4 指定键和值类型(JDK1.4或以下版本)
如果你使用JDK1.4或以下的版本,你如果需要指定键或值的类型,可以使用TypeMap来装饰。
Map map = TypedMap.decorate( new HashMap(), String. class , String. class );
map.put( " key " , " value " );
// 加入非指定的类型会抛出IllegalArgumentException,程序会停止运行
map.put( " key2 " , new Integer( 12 ));
3.8.6 根据键自动生成值的Map
Transformer upperFirstLetter = new Transformer(){
public Object transform(Object object){
String name = (String)object;
String result = name;
if (name != null &&! "" .equals(name)){
result = name.substring( 0 , 1 ).toUpperCase()
+ name.substring( 1 );
}
return result;
}
};
Map map = LazyMap.decorate( new HashMap(), upperFirstLetter);
System.out.println(map.get( " heis " ));
-> Heis
Jakarta Commons Cookbook读书笔记系列
程序员的一生其实可短暂了,这电脑一开一关,一天过去了,嚎;电脑一开不关,那就成服务器了,嚎……