讀古今文學網 > 編寫高質量代碼:改善Java程序的151個建議 > 建議143:可以選擇多種Collections擴展 >

建議143:可以選擇多種Collections擴展

為什麼這麼多的開源框架熱衷於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"式的解決方法,可以大大縮減代碼的數量,而且也不會導致代碼的可讀性降低,讀者可以在下一個項目中使用此類開源工具。