什么是最有效的 Java 集合库?[已关闭]

2022-08-31 08:06:49

什么是最有效的 Java 集合库?

几年前,我做了很多Java,当时的印象是,trove是最好(最有效)的Java Collections实现。但是当我读到“最有用的免费Java库?”问题的答案时。我注意到宝库几乎没有被提及。那么现在哪个Java Collections库是最好的呢?

更新:为了澄清,我主要想知道当我必须在哈希表中存储数百万个条目时使用什么库等(需要很小的运行时和内存占用)。


答案 1

问题(现在)是关于存储大量数据,这些数据可以使用基元类型来表示,例如 Map 中的 。在我看来,这里的一些答案非常具有误导性。让我们看看为什么。int

我从 trove 修改了基准测试,以测量运行时和内存消耗。我还将PCJ添加到此基准测试中,这是基元类型的另一个集合库(我广泛使用该库)。“官方”宝库基准测试没有将IntIntMaps与Java Collection进行比较,从技术角度来看,存储和存储可能并不相同。但是用户可能不关心这个技术细节,他希望有效地存储可表示的数据。Map<Integer, Integer>Integersintsints

首先是代码的相关部分:

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();
     }

我假设数据是原始的,这似乎是理智的。但这意味着java util的运行时受到惩罚,因为自动装箱对于原始集合框架来说不是必需的。ints

WinXP 上的运行时结果(当然没有调用),jdk1.6.0_10:gc()

                      100000 put operations      100000 contains operations 
java collections             1938 ms                        203 ms
trove                         234 ms                        125 ms
pcj                           516 ms                         94 ms

虽然这似乎已经看起来很激烈,但这并不是使用这种框架的原因。

原因是内存性能。包含 100000 个条目的地图的结果:int

java collections        oscillates between 6644536 and 7168840 bytes
trove                                      1853296 bytes
pcj                                        1866112 bytes

与原始集合框架相比,Java 集合需要的内存是原始集合框架的三倍以上。也就是说,您可以在内存中保留三倍的数据,而无需诉诸磁盘IO,这会降低运行时性能。这很重要。阅读高可扩展性以找出原因。

根据我的经验,高内存消耗是Java最大的性能问题,当然这也会导致运行时性能下降。原始集合框架可以在这里真正有所帮助。

所以:不,java.util不是答案。在询问效率时,向Java集合“添加功能”并不是重点。此外,现代JDK系列甚至不优于专门的Trove系列”。

免责声明:这里的基准测试远未完成,也不完美。它旨在将这一点带回家,这是我在许多项目中经历过的。原始集合足够有用,可以容忍可疑的API - 如果您处理大量数据。


答案 2

从检查来看,Trove似乎只是一个基元类型的集合库 - 它并不意味着要在JDK中的正常集合上添加很多功能。

就个人而言(我有偏见)我喜欢Guava(包括前Google Java Collections项目)。它使各种任务(包括集合)变得更加容易,至少是合理有效的。鉴于收集操作很少在我的代码中形成瓶颈(根据我的经验),这比集合API“更好”,后者可能更有效,但不会使我的代码可读。

鉴于Trove和番石榴之间的重叠几乎为零,也许你可以澄清你实际上从收藏库中寻找什么。