Java - 如何有效地存储大量的字符串数组

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

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

  • CSV文件-232mb
  • Lua-占用549mb的内存-157秒加载时间
  • Java-占用1,378MB的内存-12秒加载时间

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

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

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

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

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

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

点赞
用户1651073
用户1651073

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

作为 Collection,您可以使用 TreeSetTreeMap

如果您给出了 LineItem 类的良好实现(实现 equalshashcodeComparable),则可以大大优化内存使用。

2012-11-11 15:50:01
用户106261
用户106261

一个有向无环图(DAWG)是存储单词最有效的方式(无论对于内存消耗而言)。

但在这里,可能会过度使用,正如其他人所说,不要创建重复实例,只需创建多个引用指向同一实例。

2012-11-11 15:51:33
用户1535002
用户1535002
2012-11-11 15:52:31
用户1581069
用户1581069

关于您怀疑的重复字符串数据,您不需要担心,因为 Java 本身会处理这个问题,因为所有的字符串都是 final 的,并且所有的引用都指向内存中的同一个对象。

所以不确定 lua 是如何完成这项工作的,但在 Java 中应该也非常高效。

2012-11-11 16:12:22
用户1460830
用户1460830

一种简单的解决方案。您可以拥有一些 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) { //我假设 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-11 16:32:34