2012-11-11 55 views
5

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

下面是对存储器的差异和加载时间的示例:

  • CSV文件 - 232mb
  • 的Lua - 549mb在存储器 - 157秒加载
  • 爪哇 - 1,378mb在存储器 - 12加载的秒数

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

下面是CSV文件内的数据的一些背景:

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

下面是什么,可能需要加载的数据的一些例子:

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

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

+1

如果你知道该列3只持有少数可能的值,你可以[实习生他们(http://docs.oracle .com/javase/7/docs/api/java/lang/String.html#intern%28%29)以减少内存使用量。另请参阅:http://stackoverflow.com/a/1855195/829571 – assylias

+0

感谢assylias我将运行一些测试使用它。你知道它是否对短字符串有效 - 例如“去”或“去”。大多数字段包含45个字符的字符串,但有些字符串很短(4个或更少)。 – user1816198

+2

看看http://stackoverflow.com/questions/12792942/alternatives-to-java-string-interning –

回答

0

也许这篇文章能有一定的帮助:

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

+0

谢谢 - 非常有用的信息。 – user1816198

+1

我最终尝试了通过文章介绍的两个例子。事实证明,intern()保存的内存最多。我会继续尝试(特别是在我完成了更多项目之后),但这确实使我的内存使用与Lua一致,尽管载入时间更快。 – user1816198

+0

这就是为什么你不应该做链接的答案 - 链接现在已经死了。 –

0

为了优化你的内存问题,我建议使用Flyweight模式,特别是对于有很多重复的字段。您可以使用TreeSetTreeMap

如果你给一个很好的实现你的LineItem类(实现equalshashcodeComparable),您可以优化内存使用了很多。

0

DAWG

有向非循环词图是存储字的最有效方式(最佳为内存消耗反正)。

但可能过度杀伤这里,正如其他人所说不创建重复只是对同一个实例进行多次引用。

+0

谢谢我会再看看这个选项。我不会考虑任何有害的东西 - 这样做的效率越高,每次会话可以加载的数据越多,对最终用户来说也更好。 – user1816198

0

就像一个方面说明。

对于你怀疑的重复字符串数据,你不需要担心,因为java本身关心的是所有字符串都是最终的,并且所有引用都以内存中的同一对象为目标。

所以不知道怎么卢阿在做的工作,但在java中应该也相当有效率

+0

但是,如果这是真的,等于根本就没有必要,==会比较工作 – Igor

+0

好吧,equals是正确的方式,因为它是你应该比较java中的对象的方式,==也可以工作,但它只是一种因为JVM内部处理字符串的方式 –

+0

嗯,我不确定有多少内存java虚拟内部持有字符串引用,但我很确定,在足够大的程序==不会工作 – Igor

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); 
} 
+0

声音就像你试图优化已经被java优化的东西(为内存中的重复字符串保存内存),不需要这样的实现,请参阅我的答案 –

相关问题