Java - 如何有效地存储大量的String数组

时间:2012-11-11 15:42:56

标签: java csv lua

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

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

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

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

以下是CSV文件中数据的一些背景知识:

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

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

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

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

5 个答案:

答案 0 :(得分: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);
}

答案 1 :(得分:0)

为了优化您的内存问题,我建议使用Flyweight模式,特别是对于有大量重复项的字段。

作为合集,您可以使用TreeSetTreeMap

如果您为LineItem课程(实施equalshashcodeComparable)提供了良好的实施方案,那么您可以大量优化内存使用。

答案 2 :(得分:0)

DAWG

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

但是在这里可能有些过分,正如其他人所说的那样,不创建重复项只是对同一个实例进行多次引用。

答案 3 :(得分:0)

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

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

答案 4 :(得分:0)

仅作为旁注。

对于您怀疑的重复字符串数据,您不必担心这一点,因为java本身都在关注它,因为所有字符串都是final,并且所有引用都以内存中的相同对象为目标。

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