為什麼這麼多的開源框架熱衷於Collections的擴展呢?是因為我們程序(經典的定義:程序=算法+數據結構,想想看數據結構是為誰而服務的)主要處理的是一大批數據,而能容納大量數據的也就是Collections類和數組了,但是數據的格式具有多樣性,比如數據映射關係多樣,數據類型多樣等,下面我們再介紹三個比較有個性的Collections擴展工具包。
(1)fastutil
fastutil(按照Java的拼寫規則應該為FastUtil,但是官網就是這樣命名的,我們尊重官方)是一個更新比較頻繁的工具包,它的最新版本是6.3,主要提供了兩種功能:一種是限定鍵值類型(Type Specific)的Map、List、Set等,另一種是大容量的集合。我們先來看示例代碼:
//明確鍵類型的Map
Int2ObjectMap<String>map=new Int2ObjectOpenHashMap<String>();
map.put(100,"A");
//超大容量的List,注意調整JVM的Heap內存
BigList<String>bigList=new ObjectBigArrayBigList<String>(
1L+Integer.MAX_VALUE);
//基本類型的集合,不再使用Integer包裝類型
IntArrayList arrayList=new IntArrayList();
這裡要特別注意的是大容量集合,什麼叫大容量集合呢?我們知道一個Collection的最大容量是Integer的最大值(2 147 483 647),不能超過這個容量,一旦我們需要把一組超大的數據放到集合中,就必須要考慮對此進行拆分了,這會導致程序的複雜性提高,而fastutil則提供了Big系列的集合,它的最大容量是Long的最大值,這已經是一個非常龐大的數字了,超過這個容量基本上是不可能的。但在使用它的時候需要考慮內存溢出的問題,注意調節Java的mx參數配置。
(2)Trove
Trove提供了一個快速、高效、低內存消耗的Collection集合,並且還提供了過濾和攔截的功能,同時還提供了基本類型的集合,示例代碼如下:
//基本類型的集合,不使用包裝類型
TIntList intList=new TIntArrayList();
//每個元素值乘以2
intList.transformValues(new TIntFunction(){
public int execute(int element){
return element*2;
}
});
//過濾,把大於200的元素組成一個新的列表
TIntList t2=intList.grep(new TIntProcedure(){
public boolean execute(int_element){
return_element>200;
}
});
//包裝為JDK的List
List<Integer>list=new TIntListDecorator(intList);
//鍵類型確定Map
TIntObjectMap<String>map=new TIntObjectHashMap<String>();
Trove的最大優勢是在高性能上,在進行一般的增加、修改、刪除操作時,Trove的響應時間比JDK的集合少一個數量級,比fastutil也會高很多,因此在高性能項目中要考慮使用Trove。
(3)lambdaj
lambdaj是一個純淨的集合操作工具,它不會提供任何的集合擴展,只會提供對集合的操作,比如查詢、過濾、統一初始化等,特別是它的查詢操作,非常類似於DBRMS上的SQL語句,而且也會提供諸如求和、求平均值等的方法,示例代碼如下:
List<Integer>ints=new ArrayList<Integer>();
//計算平均值
Lambda.avg(ints);
//統計每個元素出現的次數,返回的是一個Map
Lambda.count(ints);
//按照年齡排序
List<Person>persons=new ArrayList<Person>();
Lambda.sort(persons, Lambda.on(Person.class).getAge()));
//串聯所有元素的指定屬性,輸出為:張三,李四,王五
Lambda.joinFrom(persons).getName();
//過濾出年齡大於20歲的所用元素,輸出為一個子列表
Lambda.select(persons, new BaseMatcher<Person>(){
@Override
public boolean matches(Object_person){
Person p=(Person)_person;
return p.getAge()>20;
}
public void describeTo(Description desc){
}
});
//查找出最大年齡
Lambda.maxFrom(persons).getAge();
//抽取出所有姓名形成一個數組
Lambda.extract(persons, Lambda.on(Person.class).getName()));
lambdaj算是一個比較年輕的開源工具,但是它符合開發人員的習慣,對集合的操作提供了"One Line"式的解決方法,可以大大縮減代碼的數量,而且也不會導致代碼的可讀性降低,讀者可以在下一個項目中使用此類開源工具。