【问题标题】:How to speed up the execution for the below code snippet如何加快以下代码片段的执行速度
【发布时间】:2018-02-14 15:55:39
【问题描述】:

我的目标是:我想读取特定文本的文件,并且我想在包含所有文件的其他目录/子目录中找到该文本。但目前程序执行速度非常慢。我多次运行该程序以检查性能。我目前在我的系统中使用 jdk1.6。任何人都可以改善执行时间或指导如何获得更好的性能?

  import java.io.BufferedReader;
    import java.io.File;
    import java.io.FileReader;
    import java.io.IOException;
    import java.util.ArrayList;
    import java.util.Arrays;
    import java.util.List;
    import java.util.Scanner;


    public class ActionFinder {
        private static final String FILENAME = "D:\\WorkSpace\\data\\Navigation.properties";
        private static ArrayList<String> allAbsoluteFilePathList = new ArrayList<String>();
    public static void main(String[] args) {
        BufferedReader br = null;
        FileReader fr = null;
        try {
            fr = new FileReader(FILENAME);
            br = new BufferedReader(fr);
            String sCurrentLine;
            ArrayList<String> actionList = new ArrayList<String>(); 


            while ((sCurrentLine = br.readLine()) != null) {

                String cmdString = sCurrentLine;

                  if(cmdString.contains(".Commands")){
                      String[] output = cmdString.split("\\.Commands");
                      actionList.add("Action."+output[0]); 

                  }

            }

              listAllTheFile("D:\\dev\\vob002\\IB\\war\\src\\main\\webapp\\web\\L001\\corporate");

            //here we are finding all the actions one by one from the file list
            for(int i=0; i < actionList.size(); i++){
                String actionName= actionList.get(i);
                searchAction(allAbsoluteFilePathList, actionName);
            }



        } catch (Exception e) {
            System.out.println("Error2: " + e.toString());

        } finally {
            try {
                if (br != null)
                    br.close();

                if (fr != null)
                    fr.close();

            } catch (Exception ex) {
                System.out.println("Error3: " + ex.toString());

            }

        }
    }


    private static void searchAction(ArrayList<String> allAbsoluteFilePathList, String actionName) {
        try {

          if(null !=allAbsoluteFilePathList){
              for(int i=0; i < allAbsoluteFilePathList.size(); i++){

                  final Scanner scanner = new Scanner(new File(allAbsoluteFilePathList.get(i)));
                  while (scanner.hasNextLine()) {
                     final String lineFromFile = scanner.nextLine();
                     if(lineFromFile.contains(actionName)) { 
                         // a match!
                         System.out.println("I found " +actionName+ " in file " + allAbsoluteFilePathList.get(i));
                         break;
                     }
                  }
              } 

          }




          }catch (Exception e) {
             System.out.println("Error1: " + e.toString());

        }

    }


    private static List<File> listAllTheFile(String directoryName) {
        File directory = new File(directoryName);
        List<File> resultList = new ArrayList<File>();

        File[] fList = directory.listFiles();
        resultList.addAll(Arrays.asList(fList));

        for (File file : fList) {

            if (file.isFile()) {
                allAbsoluteFilePathList.add(file.getAbsolutePath());
            } else if (file.isDirectory()) {
                resultList.addAll(listAllTheFile(file.getAbsolutePath()));
            }
        }

        return resultList;
    }

    }

【问题讨论】:

  • 你可以从更新你的 jdk 开始
  • 使用分析来找出代码大部分时间花在哪里,并采取相应的行动。调用计数也会有所帮助,您可能在某个地方有一个 n 平方算法。
  • @Stultuske 根据他的情况,他可能无法控制他的环境。也不一定能提高性能。

标签: java multithreading performance file


【解决方案1】:

正如在 cmets 中已经说过的,尝试通过使用配置文件来找出您的表现在哪里丢失。与此无关,这里有一些可以改进的地方(不一定与性能相关,但仍然... ;-):

fr = new FileReader(FILENAME);
br = new BufferedReader(fr);

不要使用FileReader,而是打开这样的文件:

fr = new InputStreamReader(new FileInputStream(FILENAME), "8859_1");
br = new BufferedReader(fr);

FileReader 使用系统的字符集将内容转换为可能不是您的文件编码的字符集的文本。

if (cmdString.contains(".Commands")){
    String[] output = cmdString.split("\\.Commands");
    actionList.add("Action."+output[0]); 
}

您正在调用contains 并创建一个正则表达式,其作用基本相同。每次进行拆分时,split 都会创建并编译 Pattern。所有这些都可以通过直接使用正则表达式来处理。如果您在循环外编译 Pattern,这应该有助于提高性能,因为它只执行一次而不是 n 次。

} catch (Exception e) {
    System.out.println("Error1: " + e.toString());
}

这在抛出异常时没有帮助,通常您需要完整的堆栈跟踪,因此如果您确实必须输出错误,则首选e.printStackTrace()

【讨论】:

    【解决方案2】:

    试试这样的:

    public class ActionFinder
    {
       private static final String FILENAME = "D:/WorkSpace/data/Navigation.properties";
       private static List<String> allAbsoluteFilePathList = new ArrayList<>();
       public static void main(String[] args)
       {
          try (final BufferedReader br = new BufferedReader(new InputStreamReader(
                                         new FileInputStream(FILENAME), "UTF-8")))
          {
              List<String> actionList = new ArrayList<>(); 
              while (true) // infinte loop
              {
                 final String sCurrentLine = br.readLine()
                 if (null == sCurrentLine)
                 {
                    break; // leave the loop at the end of file
                 }
                 else
                 {
                    // indexOf and substring is faster than parsing a RegEx and then
                    // instantiating an array of String objects...
                    final int pos = sCurrentLine.indexOf(".Commands");
                    if (pos >= 0)
                    {
                       actionList.add("Action." + sCurrentLine.substring(0, pos)); 
                    }
                 }
              }
              listAllTheFile(new File("D:/dev/vob002/IB/war/src/main/webapp/web/L001/corporate")
                                 .getAbsoulteFile());
              // here we are finding all the actions one by one from the file list
              for(final String actionName : actionList)
              {
                 searchAction(allAbsoluteFilePathList, actionName);
              }
          }
          catch (Exception e)
          {
             e.printStackTrace();
          }
       }
    
       private static void searchAction(List<String> allAbsoluteFilePathList, String actionName)
       {
          if (null != allAbsoluteFilePathList)
          {
             // Entering/leaving a TRY block uses resources, so placing it inside the if
            // statement seems logical...
             try
             {
                for(final String absFilePath : allAbsoluteFilePathList)
                {
                   final Scanner scanner = new Scanner(new File(absFilePath));
                   while (scanner.hasNextLine())
                   {
                      final String lineFromFile = scanner.nextLine();
                      if(lineFromFile.contains(actionName))
                      { 
                         // a match!
                         // printf is faster than String + String...
                         // Also, allAbsoluteFilePathList.get() is only called once...
                         System.out.printf("I found %s in file %s%n", actionName, absFilePath);
                         break;
                      }
                   }
                }
             }
             catch (Exception e)
             {
                e.printStackTrace();
             }
          }
       }
    
       // The return value of this result, a collection was never used...
       // Changed it to not return anything.
       private static void listAllTheFile(File directory)
       {
          final File[] fList = directory.listFiles();
          for (final File file : fList)
          {
             if (file.isFile())
             {
                // As the root call is made with an absolute path, it is not necessary to call
                // getAbsolutePath every time...
                allAbsoluteFilePathList.add(file.getPath());
             }
             else if (file.isDirectory())
             {
                // As the argument is changed to File, do not need to call getAbsolutePath
                // method on the recursion...
                listAllTheFile(file);
             }
          }
       }
    }
    

    【讨论】:

      【解决方案3】:

      看起来像你:

      1. 查找文件中的所有操作。
      2. 对于您找到的每个操作:
        1. 搜索文件列表。
        2. 对于每个文件中的每一行:
          1. 如果该操作出现在该行中,请执行一些操作。

      你会做得更好:

      1. 查找文件中的所有操作。
      2. 搜索文件列表。
        1. 对于每个文件中的每一行:
          1. 对于您找到的每个操作:
            1. 如果您的某个操作出现在行中,请执行一些操作。

      这里的主要好处是您只需搜索此文件列表一次。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2014-07-21
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多