开源的高性能Java集合:GNU Trove介绍

看过openNLP源码的人或许会注意到代码里经常引入import gnu.trove.*; 好奇之余,进行了资料搜集和总结。

Trove 是一个快速、轻量级 Collection 类的集合。Trove 提供所有标准 java.util Collections 类的更快的版本以及能够直接在原语(primitive)(例如包含 int 键或值的 Map 等)上操作的 Collections 类的版本。即它是一种开放源代码的 Java 集合包,提供了核心 Java 集合类的高效替代品,特别针对于实现其键或值是基本类型的集合
Trove 中有许许多多的高效集合,除了那 81 种不同的 HashMap 版本之外(比如 TIntIntHashMapTIntObjectHashMap 等),还有 List Set 类可以存储基本类型(如 TIntHashSetTFloatArrayList 等)。这种体系结构甚至允许你插入自己的散列策略,以便选择对你的数据集而言可能更有效(或者更灵活)的算法。当然,支持灵活的散列算法也要付出性能代价 —— 如果散列映射成为瓶颈,很可能是因为大量地使用它,这意味着散列函数被反复不断地调用。因此,散列函数中每一点多余的开销都可能成为瓶颈。(顺便说一下,如果散列函数足够简单,JIT 编译器就可能将其编译成内联函数,这样在支持灵活的散列策略的同时又不会带来额外的开销)

trove是轻量级实现java.util Collections API的第三方开源项目 官网: http://trove.starlight-systems.com/overview trove相比jdk原生的集合类有三个优势: 1、更高的性能 2、更底的内存消耗 3、除了实现原生Collections API并额外提供更强大的功能。

集合是java编程最常用的API之一,把项目的集合对象改用trove替换就能获得性能提升和内存的节省。 这是对一个项目底成本的优化方案。

下面二段代码分别测试trove和原生的集合的性能:

1. trove

public void testIterator(){
 TIntObjectMap map = new TIntObjectHashMap();

 for( int i = 0; i < 1000; i++){
 Game g = new Game();
 g.setName("最终幻想"+ i);
 g.setSize(15000 + (i << 3));
 g.setCtDate( new Date());
 map.put(i, g);
}

 int size = map.size();
 TIntObjectIterator it = map.iterator();
 for( int i = size; i > 0; i--){
it.advance();
 System. out.println(it.key() +"="+ it.value());

 if(it.key() == 3){
 Game g = new Game();
 g.setName("最终幻想13");
 g.setSize(15000 + (i << 3));
 g.setCtDate( new Date());
it.setValue(g);
}
}

 System. out.println("=======================================");
 System. out.println(map.get(3));
}

2. HashMap

public void testIterator(){
 Map map = new HashMap();

 for( int i = 0; i < 1000; i++){
 Game g = new Game();
 g.setName("最终幻想"+ i);
 g.setSize(15000 + (i << 3));
 g.setCtDate( new Date());
 map.put(i, g);
}
 Set set = map.entrySet();
 for( Iterator it = set.iterator(); it.hasNext(); ){
 Entry e = (Entry )it.next();
 System. out.println(e.getKey() +"="+ e.getValue());

 if(((Integer)e.getKey()).intValue() == 3){
 Game g = new Game();
 g.setName("最终幻想13");
g.setSize(18000);
 g.setCtDate( new Date());
e.setValue(g);
}
}

 System. out.println("=======================================");
 System. out.println(map.get(3));
}

两段的测试结果,trove花费0.001s,HashMap花费0.090s trove的测试代码使用其Map额外提供的iterator进行遍历,当然他也支持通过entrySet方式遍历。 使用SizeOf.jar计算上面两段的map占用内存的大小,trove占用214024byte,HashMap占用250128byte,可见内存方面节省的比率并是很大。 从官方下载的API中可以看中trove根据基础的数据类型实现了Map、List和Set,比如TIntObjectHashMap其key只能是int, value是继承Object的所有对象;TIntList只能存入int;TIntSet只能存入int。 在java里有些对象的hashCode和equals方法不能被覆盖(比如:String和数组),以这种对象为Map的key时就不能随心所欲,trove的提供的custom map可以解除这种约束,只需要实现HashingStrategy接口传递给Map,Map判断key是否相同时调用HashingStrategy的computeHashCode和equals代替object自身的hashCode和equals,以下是官网一个例子 For example, this code:

char[] foo, bar; 
foo = new char[] {'a','b','c'}; 
bar = new char[] {'a','b','c'}; 
System.out.println(foo.hashCode() == bar.hashCode() ?"equal":"not equal"); 
System.out.println(foo.equals(bar) ?"equal":"not equal");

produces this output: not equal not equal And so an entry stored in a java.util.HashMap with foo as a key could not be retrieved with bar, since there is no way to override hashCode() or equals() on language array objects. In a gnu.trove.THashMap, however, you can implement a TObjectHashingStrategy to enable hashing on arrays:

class CharArrayStrategy implements TObjectHashingStrategy { 
 public int computeHashCode(Object o) { 
 char[] c = (char[])o; 
 // use the shift-add-xor class of string hashing functions 
 // cf. Ramakrishna and Zobel,"Performance in Practice 
 // of String Hashing Functions"
 int h = 31; // seed chosen at random 
 for (int i = 0; i < c.length; i++) { // could skip invariants 
 h = h ^ ((h << 5) + (h >> 2) + c[i]); // L=5, R=2 works well for ASCII input 
}
 return h; 
}

 public boolean equals(Object o1, Object o2) { 
 char[] c1 = (char[])o1; 
 char[] c2 = (char[])o2; 
 if (c1.length != c2.length) { // could drop this check for fixed-length keys 
 return false; 
}
 for (int i = 0, len = c1.length; i < len; i++) { // could skip invariants 
 if (c1[i] != c2[i]) { 
 return false; 
}
}
 return true; 
}
}

总结: Trove是很值得了解和使用的一个开源项目,而且容易上手,值得学习。





 

你可能感兴趣的:(开发语言与技术)