问题
什么是最有效的Java Collections库?
几年前,我做了很多Java并且给人的印象是当时的5998501403是最好的(最有效的)Java Collections实现。但是当我读到问题"Most useful free Java libraries?"的答案时,我注意到很少提到trove。那么哪个Java Collections库现在最好?
**更新:**为了澄清,当我必须在哈希表等中存储数百万个条目时,我主要想知道要使用哪个库(需要小的运行时和内存占用)。
#1 热门回答(99 赞)
问题是(现在)关于存储大量数据,这些数据可以在Map中使用原始类型(如int
)表示。在我看来,这里的一些答案非常具有误导性。让我们看看为什么。
我修改了trove的基准来测量运行时和内存消耗。我还在此基准测试中添加了PCJ,这是基本类型的另一个集合库(我广泛使用它)。 "官方"宝库基准测试不会将IntIntMaps与Java Collection的Map<Integer, Integer>
进行比较,从技术角度来看,可能存储Integers
和存储ints
并不相同。但是用户可能并不关心这个技术细节,他希望能够有效地存储ints
的数据。
首先是代码的相关部分:
new Operation() {
private long usedMem() {
System.gc();
return Runtime.getRuntime().totalMemory() - Runtime.getRuntime().freeMemory();
}
// trove
public void ours() {
long mem = usedMem();
TIntIntHashMap ours = new TIntIntHashMap(SET_SIZE);
for ( int i = dataset.size(); i-- > 0; ) {
ours.put(i, i);
}
mem = usedMem() - mem;
System.err.println("trove " + mem + " bytes");
ours.clear();
}
public void pcj() {
long mem = usedMem();
IntKeyIntMap map = new IntKeyIntOpenHashMap(SET_SIZE);
for ( int i = dataset.size(); i-- > 0; ) {
map.put(i, i);
}
mem = usedMem() - mem;
System.err.println("pcj " + mem + " bytes");
map.clear();
}
// java collections
public void theirs() {
long mem = usedMem();
Map<Integer, Integer> map = new HashMap<Integer, Integer>(SET_SIZE);
for ( int i = dataset.size(); i-- > 0; ) {
map.put(i, i);
}
mem = usedMem() - mem;
System.err.println("java " + mem + " bytes");
map.clear();
}
我假设数据是原始的ints
,这似乎是理智的。但这意味着java util的运行时损失,因为自动装箱,这对于原始集合框架来说不是必需的。
WinXP,jdk1.6.0_10上的运行时结果(当然没有gc()
calls):
100000 put operations 100000 contains operations
java collections 1938 ms 203 ms
trove 234 ms 125 ms
pcj 516 ms 94 ms
虽然这可能看起来很激烈,但这并不是使用这种框架的原因。
原因是内存性能。包含100000int
条目的Map的结果:
java collections oscillates between 6644536 and 7168840 bytes
trove 1853296 bytes
pcj 1866112 bytes
与原始集合框架相比,Java集合需要三倍于内存。即你可以在内存中保留三倍的数据,而无需借助磁盘IO,从而降低运行时性能的大小。这很重要。阅读highscalability以找出原因。
根据我的经验,高内存消耗是Java最大的性能问题,这当然也会导致运行时性能下降。原始集合框架在这里可以提供帮助。
所以:不,java.util不是答案。在询问效率时,向Java集合添加"功能"并不是重点。现代JDK系列也是而不是"甚至超过了专门的Trove系列"。
免责声明:这里的基准远非完整,也不完美。这是为了让我在许多项目中经历过这一点。如果使用大量数据,原始集合足以容忍可疑的API -。
#2 热门回答(70 赞)
从检查来看,看起来Trove只是一个原始类型的集合库 - 它不像是在JDK中添加了许多正常集合的功能。
个人(我有偏见)我喜欢Guava(包括以前的Google Java Collections项目)。它以一种至少相当有效的方式使各种任务(包括集合)变得更加容易。鉴于集合操作很少在我的代码中形成瓶颈(根据我的经验),这比集合API"更好",集合API可能更有效但不会使我的代码可读。
鉴于Trove和Guava之间的重叠几乎为零,或许你可以从集合库中澄清你实际需要的内容。
#3 热门回答(42 赞)
我知道这是一个老帖子,这里有很多答案。但是,在建议图书馆方面,上面的答案是肤浅的,而且过于简化。没有一个图书馆在这里提供的各种基准测试中表现良好。我得出的唯一结论是,如果你关心性能和内存,特别是处理原始类型,那么它非常值得关注非jdk替代方案。
这是一个更健全的分析,在基准机制和涵盖的库方面.This是mahout开发列表中的一个线程。
涵盖的图书馆是
- HPPC
- 特洛伊
- FastUtil
- Mahout(柯尔特)
- Java Collections
2015年6月更新:不幸的是,最初的基准测试不再可用,而且有点过时.Here是其他人完成的最新(2015年1月)基准测试。它不是那么全面,也没有原始链接的交互式探索工具。