【问题标题】:Best practice for holding huge lists of data in Java在 Java 中保存大量数据的最佳实践
【发布时间】:2015-03-12 16:38:03
【问题描述】:

我正在用 Java 编写一个小型系统,在该系统中我从文本文件中提取 n-gram 特征,然后需要执行特征选择过程以选择最具鉴别力的特征。

单个文件的特征提取过程返回一个地图,其中包含每个独特特征及其在文件中的出现。我将所有文件的地图 (Map) 合并到一个地图中,其中包含从所有文件中提取的所有独特特征的文档频率 (DF)。统一的 Map 可以包含超过 10,000,000 个条目。

目前,特征提取过程运行良好,我想执行特征选择,其中我需要实现信息增益或增益比。我必须先对地图进行排序,执行计算并保存结果,以便最终获得一个列表(对于每个特征,它的特征选择分数)

我的问题是: 保存如此大量数据(~10M)并执行计算的最佳实践和最佳数据结构是什么?

【问题讨论】:

  • 看看HashMap。

标签: java data-structures feature-extraction feature-selection computation


【解决方案1】:

这是一个非常宽泛的问题,所以答案也很宽泛。解决方案取决于(至少)这三件事:

  1. 参赛作品的大小

存储 10,000,000 个整数将需要大约 40MiB 的内存,而存储 10,000,000 x 1KiB 的记录将需要超过 9GiB。这是两个不同的问题。一千万个整数存储在内存中的任何 Java 集合中都是微不足道的,而在内存中保留 9GiB 将迫使您调整和调整 Java 堆和垃圾收集器。如果条目更大,比如 1MiB,那么您可以完全忘记内存存储。相反,您需要专注于寻找良好的磁盘支持数据结构,可能是数据库。

  1. 您正在使用的硬件

在具有 8 GiB 内存的机器上存储 1000 万条 1KiB 记录与将它们存储在具有 128GiB 的服务器上是不同的。前一台机器几乎不可能的事情对后者来说是微不足道的。

  1. 您要执行的计算类型

您提到了排序,所以想到了 TreeMapPriorityQueue 之类的东西。但这是最密集的计算吗?您用来对它们进行排序的键是什么?您是否计划根据其他非关键属性来定位(获取)实体?如果是这样,那需要单独的计划。否则,您需要遍历所有一千万个条目。

您的计算是在单线程还是多线程中运行?如果您可能同时修改数据,则需要单独的解决方案。 TreeMap 和 PriorityQueue 等数据结构必须被锁定或替换为并发结构,例如 ConcurrentLinkedHashMapConcurrentSkipListMap

【讨论】:

    【解决方案2】:

    您可以使用缓存系统,查看MapDB,它非常高效并且具有树形图实现(因此您可以毫不费力地对数据进行排序)。此外,它还提供数据存储,以便在无法将数据保存在内存中时将数据保存到磁盘。

    // here a sample that uses the off-heap memory to back the map
    Map<String, String> map = DBMaker.newMemoryDirectDB().make().getTreeMap("words");
    
    //put some stuff into map
    map.put("aa", "bb");
    map.put("cc", "dd");
    

    【讨论】:

      【解决方案3】:

      我的直觉是,您可以从最初的 MapReduce 范例中获得灵感,并将您的问题划分为几个较小但相似的问题,然后汇总这些部分结果以达到完整的解决方案。

      如果您一次解决一个较小的问题实例(即文件块),这将保证您的空间消耗惩罚受限于该单个实例的空间要求。

      这种延迟处理文件的方法将不受您选择的数据结构的影响。

      【讨论】:

        猜你喜欢
        • 2011-08-24
        • 2021-11-02
        • 2018-03-11
        • 2017-01-26
        • 1970-01-01
        • 1970-01-01
        • 2013-10-23
        • 2015-09-08
        • 1970-01-01
        相关资源
        最近更新 更多