2012-07-28 62 views
0

我正在读取一个文件以供稍后解析。该文件的大小不太可能超过MB,所以在这个阶段对我来说这可能不是一个关键问题。但出于最佳实践原因,我想知道什么时候执行操作的最佳时间。执行操作的最佳时间:循环内或循环后

例子:

使用我从http://www.dzone.com/snippets/java-read-file-string粘贴的方法,我读缓冲区为一个字符串。我现在想删除所有的空格。我的方法是目前这样的:

private String listRaw; 

public boolean readList(String filePath) throws java.io.IOException { 
    StringBuffer fileData = new StringBuffer(1024); 
    BufferedReader reader = new BufferedReader(
      new FileReader(filePath)); 
    char[] buf = new char[1024]; 
    int numRead=0; 
    while((numRead=reader.read(buf)) != -1){ 
     String readData = String.valueOf(buf, 0, numRead); 
     fileData.append(readData); 
     buf = new char[1024]; 
    } 
    reader.close(); 
    listRaw = fileData.toString().replaceAll("\\s",""); 
    return true; 
} 

所以,我从我保存它的时间字符串中删除所有空白 - 在它的整体 - 一类变量。

对我来说,这意味着更少的处理,但更多的内存使用。出于最佳实践原因,我会在readData变量上应用replaceAll()操作时更好吗,因为我将它追加到fileData?使用更多的处理,但避免传递多余的空白。

我想这对于一个像我正在工作的小文件几乎没有影响,但如果它是一个200MB的日志文件呢?

这是完全取决于个案还是我有更好的一致意见?


感谢您输入的每个人。我相信你已经帮助我将自己的思维定向为编写Java的正确方向。

我已更新我的代码,以考虑所提出的要点。包括唐罗比的建议,在某些时候,我可能想保留空间。希望事情现在读得更好!

private String listRaw; 

public boolean readList(String filePath) throws java.io.IOException { 
    StringBuilder fileData = new StringBuilder(51200); 
    BufferedReader reader = new BufferedReader(new FileReader(filePath)); 
    char[] buf = new char[51200]; 
    boolean spaced = false; 
    while(reader.read(buf) != -1){ 
     for(int i=0;i<buf.length;i++) { 
      char c = buf[i]; 
      if (c != '\t' && c != '\r' && c != '\n') { 
       if (c == ' ') { 
        if (spaced) { 
         continue; 
        } 
        spaced = true; 
       } else { 
        spaced = false; 
       } 

       fileData.append(c); 
      } 
     } 
    } 
    reader.close(); 
    listRaw = fileData.toString().trim(); 
    return true; 
} 
+1

测量它并找出!这样你就知道哪个更快,而不是别人认为应该更快。 – 2012-07-28 17:19:43

+0

好点!作为一名Java新手 - 目前没有任何专门的java教科书 - 我意识到从坏习惯开始。虽然我相信在一天结束的时候我会有很多。 – 2012-07-28 17:32:41

回答

7

您最好只在最后创建并应用正则表达式替换一次。但是,你将获得由

  • 初始化StringBuilder的一个合理的规模
  • 避免循环中的String创建多得多,并且读人物直接追加到StringBuilder
  • 避免的实例化新的字符缓冲区,在任何时候,在每次迭代。

为了避免不必要的长时间临时字符串创建,您可以通过字符读取char,并且只能将字符追加到StringBuilder,如果它是not a whitespace。最后,StringBuilder将只包含好字符,并且您不需要任何replaceAll()调用。

+0

谢谢!我现在要再看一遍。我已经为stringbuilder的容量做了一个快速的Google,现在正在通过垃圾进行涉水。球公园,将几千字节加载到缓冲区完全可以吗? – 2012-07-28 17:43:29

+0

如果你的记忆允许,为什么不呢?一个StringBuilder只是一个字符数组的封装。 – 2012-07-28 17:45:36

4

实际上有在这几个代码非常显著效率低下,而且你不得不担心你提出的相对不那么重要的问题之前解决这些问题。

首先,不要在循环的每次迭代中创建新的buf对象 - 使用同一个对象!这样做没有问题 - 新数据会覆盖旧的数据,并节省对象分配(这是您可以执行的更昂贵的操作之一)。

其次,同样,请不要创建String请致电append() - 使用append的形式,该数组需要一个char数组和一个偏移量(在本例中为0)和长度(在本例中为numRead)。再次,每个循环迭代创建一个较少的对象。最后,要回答你实际问到的问题:在循环中这样做会在每次迭代中创建一个String对象,但通过我们刚才完成的调整,您将创建每个迭代的对象 - 所以在循环结束时删除空白是明确的赢家!

+0

非常感谢.append()提示。只是习惯于用不同参数的方法覆盖方法,这些方法对我来说都是陌生的。可以看到我还有很长的路要走。谢谢! – 2012-07-28 17:47:27

1

你要做解析一定程度上取决于,你可能会更好在单独的步骤去除的空间可言,和分析过程中的不理会他们。

想要删除所有空格也是相当罕见的。你确定你不想用单个空格替换多个空格吗?

+0

是的,我认为是。我要解析的文件基本上是一个多维数组,用括号和键值与等号分开。没有字符串句子,只有名字和数字值。 – 2012-07-28 17:37:55