在Java中保存大量数据的最佳实践

时间:2015-01-14 13:17:46

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

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

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

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

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

3 个答案:

答案 0 :(得分:5)

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

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

    1. 您正在使用的硬件
    2. 在具有8 GiB内存的计算机上存储一千万条1KiB记录与将它们存储在具有128GiB的服务器上的记录不同。使用前一台机器几乎不可能完成的事情对后者来说是微不足道的。

      1. 您要执行的计算类型
      2. 您已经提到了排序,因此可以想到TreeMapPriorityQueue之类的内容。但这是最密集的计算吗?你用它来排序它们的关键是什么?您是否计划根据不是关键的其他属性来定位(获取)实体?如果是这样,那需要单独计划。否则,您需要遍历所有一千万条目。

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

答案 1 :(得分:1)

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

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

这种懒惰处理文件的方法将使您选择的数据结构保持不变。

答案 2 :(得分:1)

您可以使用缓存系统,检查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");