5

我正在尝试使用 Java(更少的内存和尽可能快的访问)有效地加载大型 CSV 格式的文件(通常为 200-600mb)。目前,该程序正在使用字符串数组列表。此操作之前是使用 Lua 程序处理的,该程序使用每个 CSV 行的表和保存每个“行”表的表。

以下是内存差异和加载时间的示例:

  • CSV 文件 - 232mb
  • Lua - 549mb 内存 - 157 秒加载
  • Java - 1,378mb 内存 - 12 秒加载

如果我没记错的话,Lua 表中的重复项作为对实际值的引用存在。我怀疑在 Java 示例中,列表保存了每个重复值的单独副本,这可能与较大的内存使用量有关。

以下是 CSV 文件中数据的一些背景信息:

  • 每个字段由一个字符串组成
  • 每行中的特定字段可以包括一组字符串中的一个(例如,字段 3 可以是“红色”、“绿色”或“蓝色”)。
  • 内容中有许多重复的字符串。

以下是加载数据可能需要的一些示例:

  • 搜索所有试图与给定字符串匹配的字符串并返回匹配的字符串
  • 在 GUI 表中显示匹配项(可通过字段排序)。
  • 更改或替换字符串。

我的问题 - 是否有一个集合需要更少的内存来保存数据,但仍然提供轻松快速地搜索/排序数据的功能?

4

5 回答 5

1

一种简单的解决方案。你可以有一些HashMap你会引用所有唯一的字符串。而在ArrayList您将只引用HashMap.

就像是 :

private HashMap<String, String> hashMap = new HashMap<String, String>();

public String getUniqueString(String ns) {
   String oldValue = hashMap.get(ns);
   if (oldValue != null) { //I suppose there will be no null strings inside csv
    return oldValue;
   }        
   hashMap.put(ns, ns);
   return ns;
}

简单用法:

List<String> s = Arrays.asList("Pera", "Zdera", "Pera", "Kobac", "Pera", "Zdera", "rus");
List<String> finS = new ArrayList<String>();
for (String er : s) {
   String ns = a.getUniqueString(er);
   finS.add(ns);
}
于 2012-11-11T16:32:34.130 回答
0

为了优化你的记忆问题,我建议使用元模式,特别是对于有很多重复的字段。

作为集合,您可以使用TreeSetTreeMap

如果你给你的LineItem类(implement和Comparableequals )一个好的实现,你可以优化内存使用。hashcode

于 2012-11-11T15:50:01.457 回答
0

工作组

有向无环词图是存储词的最有效方式(无论如何最适合内存消耗)。

但这里可能有点矫枉过正,正如其他人所说,不要创建重复项,只需对同一个实例进行多次引用。

于 2012-11-11T15:51:33.957 回答
0

也许这篇文章可以提供一些帮助:

http://www.javamex.com/tutorials/memory/string_saving_memory.shtml

于 2012-11-11T15:52:31.833 回答
0

只是作为旁注。

对于您怀疑的重复字符串数据,您无需担心,因为 java 本身关心这一点,因为所有字符串都是最终的,并且所有引用都针对内存中的同一个对象。

所以不确定lua是如何完成这项工作的,但在java中它应该也很有效

于 2012-11-11T16:12:22.790 回答