如何在安卓上更快地将文本文件读取到ArrayList?

3

我在将txt文件快速读取到ArrayList中遇到了问题。如果我要读取一个0.9MB的文件,我必须等待5分钟。如果文件大小为34MB(部分原因是因为Android不接受大于1MB的文件),那么它完全无法工作。

我认为这个过程最多应该只需要几秒钟。

以下是代码:

String word; 
public ArrayList<String> dictionary = new ArrayList<String>();

public void setup() 
{

  try {
      AssetManager assetManager = getAssets();
      InputStream inputf;
      inputf = assetManager.open("dict_1.txt");
      reader = new BufferedReader(new InputStreamReader(inputf));

      word = " ";      
      while(word != null)
      {
        word =  reader.readLine();

        if (word != null)
          dictionary.add(word);
      }
      if(reader.equals("null")) println("No file found");

    } catch (NullPointerException e) {
    e.printStackTrace();
    println("No file found");
    } catch (IOException e) {
    e.printStackTrace();
    }
}

很抱歉我的英语不好,希望我的翻译能够让人理解。


首先使用Traceview来确定你的时间花在了哪里。 - CommonsWare
'reader' 不可能等于 "null",而且 NullPointerException 并不意味着 'no file found'. 我建议您修复您奇怪的错误和异常处理。 - user207421
我修复了异常处理,但如果文件读取完全很慢也不重要。 - TheDealer105
2个回答

3

当你添加元素时,ArrayList 会不断重新分配内存。随着列表的增长,这可能会消耗大量的 CPU 时间,因为需要在内存中复制一堆指针。更好的方法是将条目数作为字典文件的第一项进行存储,然后预先分配 ArrayList

 dictionary = new ArrayList<String>(numberOfEntries);

更高级的优化是使用一个不依赖于Java集合类的数据结构。根据您的需求,这可以是一个巨大的UTF-8字节数组,一次性读入内存(甚至通过内存映射文件访问)。

“可能是一个巨大的UTF-8字节数组,可以一次性读入内存(甚至通过内存映射文件访问)” - 我该如何使用它? - TheDealer105

1
你的问题是向数组列表中添加单词。在数组列表中,读取操作是常数时间 - O(1),但写入操作有可能会在支持数组中耗尽空间,重新分配和复制,因此需要O(n)时间。所以你应该使用LinkedList而不是ArrayList。它提供了效率o(1)(用于添加)。
LinkedList<String> dictionary = new LinkedList<String>();

+1 不过,我假设 OP 会想要对列表项进行某种随机访问。这些读取操作将非常缓慢 -- O(n) 缓慢。 - Tony the Pony
不幸的是,这两种方法得到了相同的结果。我改为预分配ArrayList和LinkedList,但仍然没有改变。读取时间仍然很长。 - TheDealer105

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接