apache-commons-collections

apache-commons-collections

【概要】

Commons Collections,又是一个重量级的东西,为Java标准的Collections API提供了相当好的补充。Collections当然有它存在的道理,能够把常用的数据结构归纳起来,以通用的方式去维护和访问,这应该说是一种进步,但是用起来似乎不够友好。这个时候我就会想,如果Java比现在做得更好用些,或者有一套第三方的API把我的这些需求抽象出来,实现了,该多好。Commons Collections就是这样一套API。

【包结构】

我们先来浏览一下它的包结构。

org.apache.commons.collections

此包包含在此组件的所有子包中共享的接口和实用程序。

org.apache.commons.collections.bag

该包包含 Bag和 SortedBag接口的实现。

org.apache.commons.collections.bidimap

这个软件包包含的实现 BidiMap, OrderedBidiMap和 SortedBidiMap接口。

org.apache.commons.collections.buffer

该包包含Buffer接口的实现 。

org.apache.commons.collections.collection

该包包含Collection接口的实现 。

org.apache.commons.collections.comparators

该包包含Comparator接口的实现 。

org.apache.commons.collections.functors

这个软件包包含的实现 Closure, Predicate, Transformer和 Factory接口。

org.apache.commons.collections.iterators

该包包含Iterator接口的实现 。

org.apache.commons.collections.keyvalue

此包包含集合和映射相关键/值类的实现。

org.apache.commons.collections.list

该包包含List接口的实现 。

org.apache.commons.collections.map

这个软件包包含的实现 Map, IterableMap, OrderedMap和 SortedMap接口。

org.apache.commons.collections.set

该包包含 Set和 SortedSet接口的实现。

用过Java Collections API的朋友大概或多或少会同意我如下的划分:在Java的Collections API中,不狭义的区分语法上的接口和类,把它们都看作是类的话,大致我们可以发现三种主要的类别:

1- 容器类:如Collection、List、Map等,用于存放对象和进行简单操作的;

2- 操作类:如Collections、Arrays等,用于对容器类的实例进行相对复杂操作如排序等;

3- 辅助类:如Iterator、Comparator等,用于辅助操作类以及外部调用代码实现对容器类的操作,所谓辅助,概括而通俗的来讲,就是这些类提供一种算法,你给它一个对象或者一组对象,或者仅仅是按一定的规则调用它,它给你一个运算后的答案,帮助你正确处理容器对象。比如Iterator会告诉你容器中下一个对象有没有、是什么,而Comparator将对象大小/先后次序的算法逻辑独立出来。

【分组】

List组

AbstractLinkedList

链表的抽象实现,为子类提供了许多要覆盖的点。

AbstractListDecorator

装饰另一个List以提供额外的行为。

AbstractSerializableListDecorator

AbstractListDecorator的可序列化子类。

CursorableLinkedList

一个List与实施ListIterator,允许并发修改底层列表。

FixedSizeList

装饰另一个List以修复阻止添加/删除的大小。

GrowthList

装饰另一个List以使其在添加和设置时使用大于列表大小的索引时无缝增长,从而避免大多数IndexOutOfBoundsExceptions。

LazyList

根据需要装饰另一个List以在列表中创建对象。

NodeCachingLinkedList

一种List实现,用于存储内部Node对象的缓存,以减少浪费的对象创建。

PredicatedList

装饰另一个List以验证所有添加项是否与指定的谓词匹配。

SetUniqueList

装饰一个List以确保没有像a一样重复Set。

SynchronizedList

装饰另一个List以同步其多线程环境的行为。

TransformedList

装饰另一个List以转换添加的对象。

TreeList

List针对列表中任何索引的快速插入和删除而优化的实现。

TypedList

装饰另一个List以验证添加的元素是否为特定类型。

UnmodifiableList

装饰另一个List以确保它不会被改变。

Map组

接下来看Map组。

DualHashBidiMap

其实现BidiMap使用两个HashMap实例。

DualTreeBidiMap

其实现BidiMap使用两个TreeMap实例。

DualTreeBidiMap.BidiOrderedMapIterator

内部类MapIterator。

DualTreeBidiMap.ViewMap

内部有序地图视图。

TreeBidiMap

基于Red-Black树的BidiMap实现,其中添加的所有对象都实现了Comparable接口。

UnmodifiableBidiMap

装饰另一个BidiMap以确保它不会被改变。

UnmodifiableOrderedBidiMap

装饰另一个OrderedBidiMap以确保它不会被改变。

UnmodifiableSortedBidiMap

装饰另一个SortedBidiMap以确保它不会被改变。

CaseInsensitiveMap

不区分大小写Map。

CompositeMap

装饰其他地图的地图以提供单一统一视图。

DefaultedMap

Map如果映射不包含请求的键,则装饰另一个返回默认值。

FixedSizeMap

装饰另一个Map来修复大小,防止添加/删除。

FixedSizeSortedMap

装饰另一个SortedMap来修复阻塞添加/删除的大小。

Flat3Map

一种Map实现,用于将数据存储在简单字段中,直到大小大于3。

HashedMap

一种Map实现,是一种通用的替代方案HashMap。

IdentityMap

一Map,基于匹配键和值的实现==不是equals()。

LazyMap

装饰另一个Map以根据需要在地图中创建对象。

LazySortedMap

装饰另一个SortedMap以根据需要在地图中创建对象。

LinkedMap

一个Map维护条目的顺序执行。

ListOrderedMap

装饰a Map以确保使用List维护顺序保留添加顺序。

LRUMap

Map与如果项被添加时充满其除去最近最少使用的入口固定的最大尺寸的实现。

MultiKeyMap

一个Map使用多个键映射的价值的实现。

MultiValueMap

MultiValueMap修饰另一个映射,允许它有一个键的多个值。

PredicatedMap

装饰另一个Map以验证添加内容是否与指定的谓词匹配。

PredicatedSortedMap

装饰另一个SortedMap 以验证添加内容是否与指定的谓词匹配。

ReferenceIdentityMap

阿Map到由垃圾收集被去除,其允许映射执行和匹配基于键和值==不equals()。

ReferenceMap

Map允许垃圾收集器删除映射的实现。

SingletonMap

一个Map保存单个项目,是固定大小的实现。

StaticBucketMap

StaticBucketMap是一种高效,线程安全的实现, java.util.Map在高度线程争用的环境中表现良好。

TransformedMap

装饰另一个Map以转换添加的对象。

TransformedSortedMap

装饰另一个SortedMap 以转换添加的对象。

TypedMap

装饰另一个Map以验证添加的元素是否为特定类型。

TypedSortedMap

装饰另一个SortedMap以验证添加的元素是否为特定类型。

UnmodifiableMap

装饰另一个Map以确保它不会被改变。

UnmodifiableOrderedMap

装饰另一个OrderedMap以确保它不会被改变。

UnmodifiableSortedMap

装饰另一个SortedMap以确保它不会被改变。

Commons Collections在java.util.Map的基础上扩展了很多接口和类,比较有代表性的是BidiMap、MultiMap和LazyMap。跟Bag和Buffer类似,Commons Collections也提供了一个MapUtils。

所谓BidiMap,直译就是双向Map,可以通过key找到value,也可以通过value找到key,这在我们日常的代码-名称匹配的时候很方便:因为我们除了需要通过代码找到名称之外,往往也需要处理用户输入的名称,然后获取其代码。需要注意的是BidiMap当中不光key不能重复,value也不可以。

所谓MultiMap,就是说一个key不在是简单的指向一个对象,而是一组对象,add()和remove()的时候跟普通的Map无异,只是在get()时返回一个Collection,利用MultiMap,我们就可以很方便的往一个key上放数量不定的对象,也就实现了一对多。

所谓LazyMap,意思就是这个Map中的键/值对一开始并不存在,当被调用到时才创建,这样的解释初听上去是不是有点不可思议?这样的LazyMap有用吗?我们这样来理解:我们需要一个Map,但是由于创建成员的方法很“重”(比如数据库访问),或者我们只有在调用get()时才知道如何创建,或者Map中出现的可能性很多很多,我们无法在get()之前添加所有可能出现的键/值对,或者任何其它解释得通的原因,我们觉得没有必要去初始化一个Map而又希望它可以在必要时自动处理数据生成的话,LazyMap就变得很有用了。

Collection组

接下来看看Collection组。

AbstractSerializableCollectionDecorator

AbstractCollectionDecorator的可序列化子类。

CompositeCollection

装饰其他集合的集合以提供单个统一视图。

PredicatedCollection

装饰另一个Collection以验证添加内容是否与指定的谓词匹配。

TransformedCollection

装饰另一个Collection以转换添加的对象。

TypedCollection

装饰a Collection以验证添加的元素是否为特定类型。

首先就是这个TypedCollection,它实际上的作用就是提供一个decorate方法,我们传进去一个Collection和需要的类型甄别信息java.lang.Class,它给我们创建一个全新的强类型的Collection。我们其实在bag、buffer、list、map、set这些子包中都可以找到分别对应Bag、Buffer、List、Map、Set接口的TypedXxxx版本。

方法签名:

public static Collection decorate(Collection coll, Classtype)

当它执行时,它会判断coll是否为null,同时如果coll包含数据,它会对数据进行验证,看是否满足指定的type条件。最后它返回一个强类型的Collection,当我们对这个强类型的Collection进行add操作时,它会帮我们确保添加的是正确的类型。

而这个CollectionUtils可能大家都已经想到了,就是提供一组针对Collection操作的工具/静态方法。比较有意思的是对Collection的转型、合并、减等操作。

Set组

CompositeSet

装饰一组其他集以提供单个统一视图。

ListOrderedSet

装饰另一个Set以确保迭代器保留并使用添加顺序。

MapBackedSet

装饰一个Map来获取Set行为。

PredicatedSet

装饰另一个Set以验证所有添加项是否与指定的谓词匹配。

PredicatedSortedSet

装饰另一个SortedSet以验证所有添加项是否与指定的谓词匹配。

SynchronizedSet

装饰另一个Set以同步其多线程环境的行为。

SynchronizedSortedSet

装饰另一个SortedSet以同步其多线程环境的行为。

TransformedSet

装饰另一个Set以转换添加的对象。

TransformedSortedSet

装饰另一个SortedSet以转换添加的对象。

TypedSet

装饰另一个Set以验证添加的元素是否为特定类型。

TypedSortedSet

装饰另一个SortedSet以验证添加的元素是否为特定类型。

UnmodifiableSet

装饰另一个Set以确保它不会被改变。

UnmodifiableSortedSet

装饰另一个SortedSet以确保它不会被改变。

Bag组

HashBag

实现Bag,使用a HashMap来提供数据存储。

PredicatedBag

装饰另一个Bag以验证添加内容是否与指定的谓词匹配。

PredicatedSortedBag

装饰另一个SortedBag以验证添加内容是否与指定的谓词匹配。

SynchronizedBag

装饰另一个Bag以同步其多线程环境的行为。

SynchronizedSortedBag

装饰另一个SortedBag以同步其多线程环境的行为。

TransformedBag

装饰另一个Bag以转换添加的对象。

TransformedSortedBag

装饰另一个SortedBag以转换添加的对象。

TreeBag

实现SortedBag,使用a TreeMap来提供数据存储。

TypedBag

装饰另一个Bag以验证添加的元素是否为特定类型。

TypedSortedBag

装饰另一个SortedBag以验证添加的元素是否为特定类型。

UnmodifiableBag

装饰另一个Bag以确保它不会被改变。

UnmodifiableSortedBag

装饰另一个SortedBag以确保它不会被改变。

Bag是在org.apache.commons.collections包中定义的接口,它extends java.util.Collection,而它的实现类都被放在下面的bag包中。之所以有这样一组类型,是因为我们有时候需要在Collection中存放多个相同对象的拷贝,并且需要很方便的取得该对象拷贝的个数。需要注意的一点是它虽然extends Collection,但是如果真把它完全当作java.util.Collection来用会遇到语义上的问题,详细信息参考Javadoc。

HashBag是Bag接口的一个标准实现。而BagUtils提供一组static的方法让调用者获取经过不同装饰后的Bag实例。

Buffer组

来看Buffer组。

BlockingBuffer

当空的时候装饰另一个Buffer来制作BlockingBuffer.get()和 BlockingBuffer.remove()阻止Buffer。

BoundedBuffer

装饰另一个Buffer以确保固定的最大尺寸。

BoundedFifoBuffer

BoundedFifoBuffer是一个非常有效的实现 Buffer,具有固定的大小。

CircularFifoBuffer

CircularFifoBuffer是一个先进先出缓冲区,具有固定大小,如果已满,则替换其最旧的元素。

PredicatedBuffer

装饰另一个Buffer以验证添加内容是否与指定的谓词匹配。

PriorityBuffer

二进制堆实现Buffer提供了基于Comparator排序的删除。

SynchronizedBuffer

装饰另一个Buffer以同步其多线程环境的行为。

TransformedBuffer

装饰另一个Buffer以转换添加的对象。

TypedBuffer

装饰另一个Buffer以验证添加的元素是否为特定类型。

UnboundedFifoBuffer

UnboundedFifoBuffer是一个非常有效的实现 Buffer,可以增长到任何大小。

UnmodifiableBuffer

装饰另一个Buffer以确保它不会被改变。

Buffer是定义在org.apache.commons.collections包下面的接口,用于表示按一定顺序除去成员对象的collection如队列等。具体的实现类在org.apache.commons.collections.buffer包下可以找到。

BufferUtils提供很多静态/工具方法装饰现有的Buffer实例,如将其装饰成BlockingBuffer、执行类型检查的TypedBuffer、或者不可改变的UnmodifiableBuffer等等。

最简单直接的Buffer实现类是UnboundedFifoBuffer,提供先进先出的大小可变的队列。而BoundedFifoBuffer则是对其大小进行了限制,是固定大小的先进先出队列。BlockingBuffer要在多线程的环境中才能体现出它的价值,尤其是当我们需要实现某种流水线时这个BlockingBuffer很有用:每个流水线上的组件从上游的BlockingBuffer获取数据,处理后放到下一个BlockingBuffer中依次传递。BlockingBuffer的核心特色通俗点说就是如果你向它要东西,而它暂时还没有的话,你可以一直等待直至拿到为止。PriorityBuffer则提供比一般的先进先出Buffer更强的控制力:我们可以自定义Comparator给它,告诉它怎么判定它的成员的先后顺序,优先级最高的最先走。

Comparator组

接下来我们会讲到辅助类,首先看Comparator组。

ReverseComparator

通过反转其compare方法的参数来反转另一个比较器的顺序。

ComparatorChain

ComparatorChain是一个比较器,它按顺序包装一个或多个比较器。

NullComparator

比较器将比较其他对象更低或更高的比较器。

FixedOrderComparator

比较器,它对特定的对象集强加特定的顺序。

ComparatorUtils

其实Comparator这个概念并不是Commons Collections引入的,在标准的Java Collections API中,已经明确定了一个java.util.Comparator接口,只是有很多人并不了解,Commons Collections也只是扩展了这个接口而已。这个java.util.Comparator定义如下核心方法:

public int compare(Object arg0, Object arg1)

传给它两个对象,它要告诉我们这两个对象哪一个在特定的语义下更“大”,或者两者相等。如果arg0 > arg1,返回大于0的整数;如果arg0 = arg1,返回0;如果arg0 < arg2,返回小于0的整数。

我们看看Commons Collections给我们提供了哪些Comparator的实现类(都在org.apache.commons.collections.comparators包下面):

BooleanComparator – 用于排序一组 Boolean 对象,指明先 true 还是先 false ;

ComparableComparator – 用于排序实现了 java.lang.Comparable 接口的对象(我们常用的 Java 类如 String 、 Integer、 Date 、 Double 、 File 、 Character 等等都实现了 Comparable 接口);

ComparatorChain – 定义一组 Comparator 链,链中的 Comparator 对象会被依次执行;

FixedOrderComparator – 用于定义一个特殊的顺序,对一组对象按照这样的自定义顺序进行排序;

NullComparator – 让 null 值也可参与比较,可以设定为先 null 或者后 null ;

ReverseComparator – 将原有的 Comparator 效果反转;

TransformingComparator – 将一个 Comparator 装饰为具有 Transformer 效果的 Comparator 。

// 有关 Transformer 的内容会在以后的笔记中讲到。

以上除了ComparatorChain之外,似乎都是实现一些很基本的比较方法,但是当我们用ComparatorChain将一组Comparator串起来之后,就可以实现非常灵活的比较操作。

Predicate组

接下来看Predicate组

AndPredicate

谓词实现,如果两个谓词都返回true,则返回true。

OrPredicate

谓词实现,如果其中一个谓词返回true,则返回true。

AllPredicate

谓词实现,如果所有谓词都返回true,则返回true。

OnePredicate

谓词实现,如果只有一个谓词返回true,则返回true。

NonePredicate

谓词实现,如果没有谓词返回true,则返回true。

PredicateUtils

Predicate是Commons Collections中定义的一个接口,可以在org.apache.commons.collections包中找到。其中定义的方法签名如下:

public boolean evaluate(Object object)

它以一个Object对象为参数,处理后返回一个boolean值,检验某个对象是否满足某个条件。其实这个Predicate以及上一篇笔记提到的Comparator还有我们即将看到的Transformer和Closure等都有些类似C/C++中的函数指针,它们都只是提供简单而明确定义的函数功能而已。

跟其他组类似,Commons Collections也提供了一组定义好的Predicate类供我们使用,这些类都放在org.apache.commons.collections.functors包中。当然,我们也可以自定义Predicate,只要实现这个Predicate接口即可。在Commons Collections中我们也可以很方便使用的一组预定义复合Predicate,我们提供2个或不定数量个Predicate,然后交给它,它可以帮我们处理额外的逻辑,如AndPredicate处理两个Predicate,只有当两者都返回true它才返回true;AnyPredicate处理多个Predicate,当其中一个满足就返回true,等等。

Transformer组

接下来看Transformer组。

ChainedTransformer

将指定变压器链接在一起的变压器实现。

SwitchTransformer

Transformer实现调用其谓词返回true的转换器,如switch语句。

TransformerUtils

我们有时候需要将某个对象转换成另一个对象供另一组方法调用,而这两类对象的类型有可能并不是出于同一个继承体系的,或者说出了很基本的Object之外没有共同的父类,或者我们根本不关心他们是不是有其他继承关系,甚至就是同一个类的实例只是对我们而言无所谓,我们为了它能够被后续的调用者有意义的识别和处理,在这样的情形,我们就可以利用Transformer。除了基本的转型Transformer之外,Commons Collections还提供了Transformer链和带条件的Transformer,使得我们很方便的组装出有意义的转型逻辑。

假定我们在处理员工聘用时,需要将原来的Applicant对象转换为Employee对象,而Applicant类和Employee类无论继承关系、字段内容、具体业务职能等等都不是同一派系的,只是某些字段是相关的,且要求必要的转换,那么这个时候我们使用Transformer就可以比较方便的实现这项功能,并且由于它的实现是灵活的、模块化的,使得今后的维护也变得清晰和易于处理。

Closure组

ChainedClosure

Closure实现将指定的闭包链接在一起

IfClosure

Closure实现充当if语句,基于谓词调用一个或其他闭包。

WhileClosure

闭包实现,在满足条件之前重复执行闭包,如do-while或while循环。

ClosureUtils

Closure这一组接口和类提供一个操作对象的execute方法,为我们在处理一系列对象时可以将处理逻辑分离出来。理论上讲,使用Transformer也可以达到类似的效果,只要输出对象和输入对象是同一个对象就好,但是Closure接口定义的execute方法返回void,并且从效果和功能区分上,Closure可以更好的诠释对象处理或执行的意思。而事实上,ClosureUtils中也提供了一个asClosure方法包装一个现成的Transformer。

Iterator组

来看最后一组 – Iterator。

LoopingIterator

迭代器在到达结束时重新启动。

ArrayListIterator

实现一个ListIterator数组。

FilterIterator

Iterator使用谓词来装饰另一个来过滤元素。

UniqueFilterIterator

一个只返回“唯一”对象的FilterIterator。

IteratorUtils

java.util.Iterator接口定义了标准的Collection遍历方法,但是如果不做改变的使用它,我们得到的是从头到尾一次性的遍历。假如我们需要循环遍历,假如我们需要遍历某一段,假如我们需要遍历满足某些条件的元素,等等等等,我们就不能完全依赖于这个Iterator的标准实现了。除非我们宁可在此基础上在调用的代码中多加一些判断,不过这样的话代码就会显得混乱,时间长了就容易变得难以维护。Commons Collections的这一组Iterator为我们带来了便利。

【举例介绍】

commons-collections使用介绍之List

CursorableLinkedList(可链接列表)是List的一种实现,提供了一个列表迭代器并且允许修改列表。CursorableLinkedList支持所有可选列表的操作。它继承自AbstractLinkedList,提供了stack/queue/dequeue的操作。这个类的主要功能是能够在同一时间修改列表和迭代器。listIterator()和cursor()方法都提供了访问一个继承自ListIterator的Cursor实例。游标允许更改列表时并发修改迭代器。需要注意的是,iterator()方法和子列表不会提供这种光标行为。CursorableLinkedList不是线程同步的。

  public void test(){
      CursorableLinkedList linkedList = new CursorableLinkedList();
      linkedList.add("center");
      linkedList.addFirst("first");
      linkedList.addLast("last");
      System.out.println(linkedList);
      Cursor cursor = linkedList.cursor();
      if (cursor.hasNext())
      {
         Object o = cursor.next();
         System.out.println("使用游标移除元素:" + o);
         cursor.remove();
      }
      cursor.close();
      System.out.println(linkedList);
      Iterator iterator = linkedList.iterator();
      if (iterator.hasNext())
      {
         Object o = iterator.next();
         System.out.println("使用迭代器移除元素:" + o);
         iterator.remove();
      }
      System.out.println(linkedList);
   }

[first, center, last] 
使用游标移除元素:first 
[center, last] 
使用迭代器移除元素:center 
[last]

FixedSizeList(固定大小的列表)修饰另一个列表防止添加/删除并且固定列表大小。add、remove、clear和retain操作是不被支持的,set方法是允许的但是不会影响列表大小。

 public void test() {
      ArrayList src = new ArrayList();
      src.add("11");
      src.add("22");
      src.add("33");
      src.add("44");
      FixedSizeList fixedSizeList = (FixedSizeList) FixedSizeList.decorate(src);
      System.out.println(fixedSizeList);
      System.out.println("列表最大长度:" + fixedSizeList.maxSize());
      // 更改列表指定索引位置元素
      fixedSizeList.set(0, "55");
      System.out.println(fixedSizeList);
      // 移除元素,不被支持
      // fixedSizeList.remove(0);
   }

[11, 22, 33, 44] 
列表最大长度:4 
[55, 22, 33, 44]

GrowthList(增长列表)修饰另一个列表,可以使其在因set或add操作造成索引超出异常时无缝的增加列表长度,可以避免大多数的IndexOutOfBoundsException。

   public void test()
   {
      ArrayList src = new ArrayList();
      src.add("11");
      src.add("22");
      GrowthList growthList = (GrowthList) GrowthList.decorate(src);
      System.out.println(growthList);
      // 索引超出,自动增长
      growthList.set(3, "44");
      System.out.println(growthList);
   }

[11, 22] 
[11, 22, null, 44]

LazyList(懒惰 列表)修饰另一个列表,当调用get方法时,如果索引超出列表长度,列表会自动增长,我们可以通过一个工厂获得超出索引位置的值。LazyList和GrowthList都可以实现对修饰的列表进行增长,但是LazyList发生在get时候,而GrowthList发生在set和add时候,我们也可以混合使用这两种列表。

 public void test()
   {
      ArrayList src = new ArrayList();
      src.add("11");
      src.add("22");
      Factory factory = new Factory()
      {
         @Override
         public Object create()
         {
            return "new";
         }
      };
      LazyList lazyList = (LazyList) LazyList.decorate(src, factory);
      System.out.println(lazyList);
      // 获得超出索引位置的元素,自动增长
      System.out.println(lazyList.get(3));
      System.out.println(lazyList);
   }

[11, 22] 
new 
[11, 22, null, new]

PredicatedList(预校验列表)修饰另一个列表,在执行add的时候对添加元素进行校验,校验不通过则抛出IllegalArgumentException异常。commons-collections已经为我们提供了一些验证的实现:

类名

说明

AllPredicate

多个断言组合,如果断言数组为空则允许所有元素,否则只有当所有断言都为真才允许添加

AndPredicate

两个断言组合,当断言都为真时允许添加,否则不允许

AnyPredicate

多个断言组合,如果断言数组为空则不允许所有元素,否则只要有一个断言为真则允许添加

EqualPredicate

如果添加的元素和断言中的元素相等(equals),则允许添加

ExceptionPredicate

总是会抛出一个FunctorException异常

FalsePredicate

不允许添加任何元素

IdentityPredicate

如果添加的元素和断言中的元素为同一个(==),则允许添加

InstanceofPredicate

允许添加指定类型的实例

NonePredicate

多个断言组合,如果断言数组为空则允许所有元素,否则只要有一个断言为真则不允许添加,

NotNullPredicate

元素不为null则允许添加

NotPredicate

断言为真则不允许添加

NullIsExceptionPredicate

元素为null,则抛出一个FunctorException异常,否则断言为真则允许添加

NullIsFalsePredicate

元素为null,则不允许添加,否则断言为真则允许添加

NullIsTruePredicate

元素为null或断言为真允许添加

NullPredicate

仅允许添加null元素

OnePredicate

多个断言组合,如果断言数组为空则不允许所有元素,否则只有一个断言为真时允许添加

OrPredicate

两个断言组合,当断言有一个为真时允许添加,否则不允许

TransformedPredicate

对元素进行变换后断言为真则允许添加

TransformerPredicate

对元素进行变换后,变换结果为真则允许添加

TruePredicate

允许添加所有元素

UniquePredicate

不允许添加重复元素

   public void test()
   {
      PredicatedList predicatedList = (PredicatedList) PredicatedList.decorate(
            new ArrayList(), NotNullPredicate.INSTANCE);
      predicatedList.add("123");
      // 抛出异常
      // predicatedList.add(null);
   }

SetUniqueList(设置元素唯一列表)实现了一个不允许重复元素的列表,有点和Set类似。

  public void test()
   {
      SetUniqueList setUniqueList = SetUniqueList
            .decorate(new ArrayList());
      setUniqueList.add("11");
      setUniqueList.add("11");
      setUniqueList.add("22");
      System.out.println(setUniqueList);
   }

[11, 22]

SynchronizedList(同步列表)修饰另一个列表,使其可以在多线程环境下同步。和Vector类似。

TransformedList(转换列表)修饰另一个列表,在add和set的时候对元素进行转换后在执行相关操作。

 public void test()
   {
      TransformedList transformedList = (TransformedList) TransformedList
            .decorate(new ArrayList(),
                  StringValueTransformer.getInstance());
      // 添加时会将其转换为字符串
      transformedList.add(new Integer(20));
      System.out.println(transformedList.get(0).getClass());
      System.out.println(transformedList);
   }

class Java.lang.String 
[20]

TreeList(树列表)实现了优化的快速插入和删除任何索引的列表。这个列表内部实现利用树结构,确保所有的插入和删除都是O(log n)。

TypedList(键入列表)修饰了另一个列表,使其只能添加指定类型的实例,修饰后的列表本质上就是使用InstanceofPredicate断言的PredicatedList。

UnmodifiableList(不可修改列表)修饰另一个列表,使列表不允许被修改。

commons-collections使用介绍之Map

CaseInsensitiveMap(不敏感)是一个对键的大小写不敏感的Map,在将键添加或与其它键比较之前,会将其转换为小写字符串。

  public void test()
   {
      CaseInsensitiveMap caseInsensitiveMap = new CaseInsensitiveMap();
      caseInsensitiveMap.put("name", "在线");
      caseInsensitiveMap.put("NAME", "在线");
      System.out.println(caseInsensitiveMap);
      System.out.println(caseInsensitiveMap.get("nAme"));
      }

{name=中移在线} 
中移在线

CompositeMap(复合的)修饰另一个Map。添加和移除操作使用可插拔的策略,如果没有提供策略,添加和删除是不支持的。

   public void test()
   {
      CompositeMap compositeMap = new CompositeMap();
      compositeMap.addComposited(new HashMap());
      MapMutator mapMutator1 = new MapMutator()
      {
         @Override
      public Object put(CompositeMap map, Map[] composited, 
      Object key,Object value)
         {
            return composited[0].put(key, value);
         }
      };  
      compositeMap.setMutator(mapMutator1);
      compositeMap.put("name", "JIANGGUJIN");
      System.out.println(compositeMap.get("name"));  
      }

JIANGGUJIN

DefaultedMap(默认)修饰另一个Map,当使用get方法时,如果键不存在,将返回默认对象。

 DefaultedMap defaultedMap = new DefaultedMap("NULL");
      defaultedMap.put("name", "中移在线");
      System.out.println(defaultedMap);
      System.out.println(defaultedMap.get("NAME"));

{name=中移在线} 
NULL

FixedSizeMap修饰另一个Map防止添加/删除并且固定Map大小。仅允许对已有的键进行值的修改,影响到Map大小的操作都是不被支持的。

public void test()
   {
      HashMap src = new HashMap();
      src.put("name", "在线");
      FixedSizeMap fixedSizeMap = 
      (FixedSizeMap) FixedSizeMap.decorate(src);
      fixedSizeMap.put("name", "121");
      // 不支持
      //fixedSizeMap.put("name1", "121");
      System.out.println(fixedSizeMap);
      }

{name=121}
IdentityMap提供了一个Map的实现,与其他Map不同的是,在IdentityMap中匹配键和值是通过==而不是equals()。

例子:

 IdentityMap identityMap = new IdentityMap();
  String key1 = "name";
  String key2 = new String("name");// key1 != key2
  identityMap.put(key1, "在线");
  System.out.println(identityMap);
  System.out.println(identityMap.get(key1));
  System.out.println(identityMap.get(key2));

{name=中移在线} 
 中移在线 
 null

LazyMap修饰另一个Map。当执行get()方法时,如果键值不存在,则返回工厂创建的对象。

public void test()
   {
      Factory factory = new Factory()
      {
         @Override
         public Object create()
         {
            return "NULL";
         }
      };
  LazyMap lazyMap = (LazyMap) LazyMap.
  decorate(new HashMap(), factory);
  lazyMap.put("name", "在线");
  System.out.println(lazyMap);
  System.out.println(lazyMap.get("hello"));
  }

{name=中移在线} 
NULL

LinkedMap实现了一个可维护顺序的Map,键的顺序为插入的顺序。

public void test()
   {
      LinkedMap linkedMap = new LinkedMap();
      for (int i = 0; i < 10; i++)
      {
         linkedMap.put("key" + i, "value" + i);
      }
      System.out.println(linkedMap);
      String key = "key5";
      System.out.println(linkedMap.previousKey(key));
      System.out.println(linkedMap.nextKey(key));
      System.out.println(linkedMap.indexOf(key));
      }
  ---------------------


{key0=value0, key1=value1, key2=value2, key3=value3, key4=value4, key5=value5, key6=value6, key7=value7, key8= value8, key9=value9} 
key4 
key6 
5

MultiKeyMap实现了一个允许多个键的Map,允许将多个键关联到一个值上。

MultiKeyMap multiKeyMap = new MultiKeyMap();	
  multiKeyMap.put("name", "NAME", "在线");
  System.out.println(multiKeyMap);
  System.out.println(multiKeyMap.get("name"));
  System.out.println(multiKeyMap.get("NAME"));
  System.out.println(multiKeyMap.get("name", "NAME"));

{MultiKey[name, NAME]=中移在线} 
 null 
 null 
 中移在线

MultiValueMap允许一个键关联多个值。

public void test()
   {
      MultiValueMap multiValueMap = new MultiValueMap();
      ArrayList list = new ArrayList();
      list.add("value1");
      list.add("value2");
      list.add("value3");
      list.add("value4");
      multiValueMap.putAll("key", list);
      System.out.println(multiValueMap);
      System.out.println(multiValueMap.get("key"));
   }

{key=[value1, value2, value3, value4]} 
[value1, value2, value3, value4]

PredicatedMap修饰另一个Map。在添加数据的时候进行校验。可参考PredicatedList用法。

ReferenceMap(参考 )使用软引用的方式维护数据,允许数据被垃圾收集器清理。

ReferenceIdentityMap结合了IdentityMap和ReferenceMap,使用软引用维护数据并且使用==匹配数据。

TransformedMap修饰另一个Map,在添加数据时,先对键和值进行转换。

TypedMap修饰另一个Map,限定了键和值的数据类型。

UnmodifiableMap修饰另一个Map,使其不允许被修改。

commons-collections使用介绍之Bag

Bag是在org.apache.commons.collections包中定义的接口,它extends java.util.Collection,而它的实现类都被放在下面的bag包中。之所以有这样一组类型,是因为我们有时候需要在Collection中存放多个相同对象的拷贝,并且需要很方便的取得该对象拷贝的个数。需要注意的一点是它虽然extends Collection,但是如果真把它完全当作java.util.Collection来用会遇到语义上的问题。

HashBag使用HashMap作为数据存储,是一个标准的Bag实现。

   public void test()
   {
      HashBag hashBag = new HashBag();
      String s1 = "s1";
      String s2 = "s2";
      hashBag.add(s1);
      hashBag.add(s1);
      hashBag.add(s2, 3);
      // 获得包中元素迭代器
      Iterator iterator = hashBag.iterator();
      System.out.println("包中元素为:");
      while (iterator.hasNext())
      {
         System.out.println(iterator.next());
      }
      System.out.println("包中元素个数为:" + hashBag.size());
      System.out.println("包中entity1个数为:" + hashBag.getCount(s1));
      System.out.println("去重后个数为:" + hashBag.uniqueSet().size());
   }

运行结果:

包中元素为: 
s1 
s1 
s2 
s2 
s2 
包中元素个数为:5 
包中entity1个数为:2 
去重后个数为:2

TreeBag使用TreeMap作为数据存储,用法与HashBag类似,只是TreeBag会使用自然顺序对元素进行排序。

   public void test()
   {
      TreeBag treeBag = new TreeBag();
      String s1 = "s1";
      String s2 = "s2";
      String s3 = "s3";
      hashBag.add(s3);
      hashBag.add(s1);
      hashBag.add(s2);
      // 获得包中元素迭代器
      Iterator iterator = treeBag.iterator();
      System.out.println("包中元素为:");
      while (iterator.hasNext())
      {
         System.out.println(iterator.next());
      }
      System.out.println("包中元素个数为:" + treeBag.size());
      System.out.println("包中entity1个数为:" + treeBag.getCount(s1));
      System.out.println("去重后个数为:" + treeBag.uniqueSet().size());
   }

运行结果:

包中元素为: 
s1 
s2 
s3 
包中元素个数为:3 
包中entity1个数为:1 
去重后个数为:3

你可能感兴趣的:(java,apache,commons,java,apahce,collections,工具包,优化)