性能优化:Trove集合库
来源:互联网 发布:数控铣床编程简单100例 编辑:程序博客网 时间:2024/06/05 11:09
1 初见Trove
昨天在Startup News上看到一篇文章:优化技巧分享:把内存消耗降低至原来的1/20。里边提到了一个案例,Java应用中如何降低内存消耗,总结了他的优化过程:
- 开始时,存放1.3M个Person对象,消耗堆空间1.5GB
- 修改为java.util.HashMap
2 使用Trove
- 如果使用Maven的话,可使用下面的配置
<dependency> <groupId>net.sf.trove4j</groupId> <artifactId>trove4j</artifactId> <version>3.0.3</version></dependency>
- 常用方法和JDK集合类是一样的,方便迁移
TIntObjectMap<String> ints = new TIntObjectHashMap<String>();ints.put(100, "John");ints.put(101, "Tom");System.out.println(ints.get(100));
Trove相当于把JDK集合类都针对原生类型处理了一遍,例如int,常见的类有
TIntList、TIntObjectMap、TObjectIntMap、TIntSet,可想而知,维护Trove的工作量是挺大的。
Trove还提供了开放寻址法的Map,Set,LinkedList实现,可以参考Enhance Collection Performance with this Treasure Trove的做法,类似于:
public class CollectionFactory { static boolean useTrove = true; /** * Return a hashmap based on the properties */ public static Map getHashMap() { if ( useTrove ) return new THashMap(); else return new HashMap(); } /** * Return a hashset based on the properties */ public static Set getHashSet() { if ( useTrove ) return new THashSet(); else return new HashSet(); } /** * Return a linkedlist based on the properties */ public static List getLinkedList() { if ( useTrove ) return new TLinkedList(); else return new LinkedList(); }}
- 迭代集合中的元素
Trove不推荐JDK的entryXX的做法,而是采用了forEach的回调方式。
代码显得更好看些,另外内存方面也有优势,因为使用entryXX的做法,需要创建一个新的数组。
TIntObjectMap<String> ints = new TIntObjectHashMap<String>();ints.put(100, "John");ints.put(101, "Tom");ints.forEachEntry(new TIntObjectProcedure<String>() { public boolean execute(int a, String b) { System.out.println("key: " + a + ", val: " + b); return true; }});ints.forEachKey(new TIntProcedure() { public boolean execute(int value) { System.out.println("key: " + value); return true; }});ints.forEachValue(new TObjectProcedure<String>() { public boolean execute(String object) { System.out.println("val: " + object); return true; }});
- 自定义Hash策略
我们知道,在JDK集合类里边,有时候是没法自定义Hash策略的,例如String。
不过Trove提供了自定义Hash策略的功能,让你可以根据数据特性进行优化。
public static void main(String[] args) { char[] foo = new char[]{'a', 'b', 'c'}; char[] bar = new char[]{'a', 'b', 'c'}; TCustomHashMap<char[], String> ch = new TCustomHashMap<char[], String>(new CharArrayStrategy()); ch.put(foo, "John"); ch.put(bar, "Tom");}class CharArrayStrategy implements HashingStrategy<char[]> { public int computeHashCode(char[] c) { // 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(char[] c1, char[] c2) { 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; }}
3 Trove内幕
Trove是以减少内存消耗为主要目的的,同时也要保持性能。我们这里简单描述一下Trove的实现内幕。
这里有有另外一篇文章可以参考:性能观察: Trove 集合类
- 直接使用原生类型,而不是包装类型
JDK5的自动封箱机制,让我们可以暂时忽略原生类型和包准类型的区别。自动封箱机制只是一种语法糖,实际上并没有提高效率。
直接使用原生类型替代包装类型,明显可以占用更小的内存、运行起来也更有效率。对于基本类型的集合组合,Trove都提供了
等价的集合类。
- 使用开放寻址法,而不是链地址法
大多数的JDK集合类都是采用链地址法实现的,它需要一个地址表,并且元素之间需要链表结点,而Trove采用开放寻址法,
虽然需要保持足够的空闲位置(装载因子小于0.5),但因为不需要链表结点,所以总体上内存占用要更少,性能还要更快一些。
- HashSet不再通过内置HashMap实现
JDK的HashSet是通过内置一个HashSet来实现的,所以白白浪费了value的空间。
Trove提供的THashSet和其他基本类型的HashSet,都不再采用这种方式,直接使用开放地址存储。
- 采用素数长度大小的数组
为了最大程度避免hash冲突,除了保持较小的装载因子,还采用了素数长度大小的数组。具体见gnu.trove.impl.PrimeFinder
- 采用代码生成进行维护
虽然这个和性能没什么关系。但是我们也知道要维护这么多的原生类型集合类,重复的逻辑多但没法重用,是个很纠结的事情。
Trove采用代码模板,生成大量的类,通过这种方式,可以大大减少维护的工作量。
4 总结
JDK作为通用集合类,大多数情况下我们还是会优先选择的。不过,在一些性能敏感的地方,或者Trove可以提供更好的选择。
作为靠谱的java开发人员,Trove应该像apache commons、google guava那样,存放在你的工具箱里边。
- 性能优化:Trove集合库
- 性能优化:Trove集合库
- 性能观察: Trove 集合类
- 性能观察: Trove 集合类
- 【3】性能观察:Trove集合类
- 【3】性能观察:Trove集合类
- 开源的高性能Java集合:GNU Trove介绍
- Trove集合类
- Trove 集合类学习
- Android性能优化集合
- Java数组/集合性能优化
- 网站性能优化大集合
- WEB前端性能优化集合
- android-性能优化之集合类优化
- Java 快速、轻量级 Collection 类的集合GNU Trove
- Mongodb固定集合和性能优化
- mongoDb固定集合与性能优化
- java性能优化总结(2):集合
- Http、TCP/IP、UDP
- WebSphere数据源中的连接被意外关闭案例
- Codeforces 673D Bear and Two Paths【贪心】
- Java中有关Null的注意事项
- 【译】Android 7.0 for Developers
- 性能优化:Trove集合库
- 在linux下安装JDK
- 2.12.1 求数列的和
- vue自定义日期组件
- 搭建ftp图片服务器,通过Nginx来显示
- 如何在android studio中添加so文件
- 贝叶斯模型比较
- JSP九大内置对象
- nginx 配置文件