Java 加载到内存中的文件比磁盘上的文件大

Java 加载到内存中的文件比磁盘上的文件大,java,memory,jtable,out-of-memory,memory-mapped-files,Java,Memory,Jtable,Out Of Memory,Memory Mapped Files,我正在将java中的文本文件加载到内存中。文本文件的大小为100 MB,包含数千行字符串、整数或双精度类型 一旦它被加载到内存中,尽管如果我使用64位JDK编译它会占用整个1GB或更多的空间 这是一个问题,因为我需要加载更大的文件 它们作为精确的数据类型存储在arraylist中。我查看了MemoryMappedFile,虽然我不确定它们是否能提供我所需的功能,但文本文件被制表符删除了40列,我需要在JTable中显示,同样,如果我需要在JTable中显示,我不认为我可以使用内存映射文件,但可能

我正在将java中的文本文件加载到内存中。文本文件的大小为100 MB,包含数千行字符串、整数或双精度类型

一旦它被加载到内存中,尽管如果我使用64位JDK编译它会占用整个1GB或更多的空间

这是一个问题,因为我需要加载更大的文件

它们作为精确的数据类型存储在arraylist中。我查看了MemoryMappedFile,虽然我不确定它们是否能提供我所需的功能,但文本文件被制表符删除了40列,我需要在JTable中显示,同样,如果我需要在JTable中显示,我不认为我可以使用内存映射文件,但可能我错了

如有任何建议,将不胜感激

数据按如下方式存储,我之所以需要将所有数据都存储在内存中,是因为在计算的任何时候,我都需要访问文件中的任何行

这是在我的JTable表模型中,请注意,传递给tablemodel的rowdata在之后会被清空,以确保内存中没有重复的副本

private Object[][] data;

public TableModel(ArrayList<String> headers, RowData[] importedData)
{                
   columnNames = new String[headers.size()];
   data = new Object[importedData.length][headers.size()];

   for (int i = 0; i < headers.size(); i++) // extract the column names
    {                                        // for the table
        this.columnNames[i] = headers.get(i);
    }

   for (int i = 0; i < importedData.length; i++)  // extracting the data
   {                                              // for the table
       for (int j = 0; j < headers.size(); j++)
       {
            this.data[i][j] = importedData[i].myList.get(j);
       }
   }
}
私有对象[][]数据;
公共表模型(ArrayList标题,RowData[]导入数据)
{                
columnNames=新字符串[headers.size()];
数据=新对象[importedData.length][headers.size()];
for(int i=0;i
我已经在.NET平台上解决了这个问题,原因可能是一样的

如果您在硬盘上的文件中使用了字符串“hello”,这并不意味着
新字符串(“hello”)
也会占用内存中的2x5字节

在.NET中,字符串的新初始化需要约40字节,因为内存中有两件事与对象定义本身有关

我发现了一篇关于java的好文章-。它显示了确切的数字

这一点与您提到的其他类型有关。在像
int
这样的数字类型中,唯一的内存占用save

文件中的数字
124567
只是字符串,它采用2xsize字符串表示法,例如,在UTF-8的情况下为2x7bytes。另一方面,内存中的
int
实例占用4个字节


说到这一点,它有很大的意义,因为它可以节省硬盘空间。

我认为您在内存结构中使用了很多小对象。可能会给你带来额外的开销。根据我的经验,减少内存消耗的最佳方法是使用普通阵列。可以将此数组包装到其他结构中。当我使用这种方法时,它为我节省了70%的内存。它不是干净的代码,但如果您需要节省内存,它会工作的

还要逐行从文件中读取数据。在读取下一行之后,将这些数据放入您的结构中

例如,如果需要两个文件id和名称,可以创建如下内容:

public class DataStructure {

    private final static int SIZE_STEP = 32;

    private int size = 0;
    private int[] ids = new int[SIZE_STEP];
    private String[] names = new String[SIZE_STEP];

    public void add(int id, String name) {
        if(size >= ids.length) {
            ids = Arrays.copyOf(ids, ids.length + SIZE_STEP);
            names = Arrays.copyOf(names, names.length + SIZE_STEP);
        }
        ids[size] = id;
        names[size] = name;
        size++;
    }

    public int getId(int index) {
        return ids[index];
    }

    public String getName(int index) {
        return names[index];
    }
}
其他方法可以是分页。例如,当您仅显示20条记录并提供页面导航时

文本文件的大小为100 MB,包含数千行字符串、整数或双精度类型

不,没有。它包含数千行文本,以文本十进制格式表示字符串、整数或双精度。任何类型的文本文件中都没有对象。因此,当您将其加载到内存中并将其转换为对象格式时,内存使用将发生变化

这是一个问题,因为我需要加载更大的文件

所以不要加载它们。逐行或逐段地处理它们,不管在文件中是什么意思,或者使用数据库

文本文件被制表符删除,有40列需要显示在JTable中


您不需要在
JTable中的40列中显示数百兆字节的数据。
这意味着数千行。这只是一个用户界面噩梦。无法使用。重新设计UI以使用过滤器,重新设计数据以使用数据库,重新设计应用程序以加载过滤后的数据并显示它

请上传此文件的代码。您使用的内存结构是什么?是否需要将整个文件加载到内存中?在一个JTable中显示100MB的数据听起来是个坏主意。我添加了代码,我不一定需要一次显示所有数据,但如果用户需要,我需要访问它。出于计算目的,我可能需要在运行计算时随时访问数千行中的任何一行。