【问题标题】:Can I check the size of a collection as it is being populated我可以在填充集合时检查集合的大小吗
【发布时间】:2012-08-28 02:02:45
【问题描述】:

我正在使用以下 Apache Commons 类在 Java 文件系统中列出文件:

Collection<File> allFiles = FileUtils.listFiles(rootDirectory, null, recursive);

这是一个很长的过程,最多可能需要 5 分钟。

有什么方法可以检查集合的大小在填充时?

我尝试从一个单独的线程访问它,但在进程准备好之前得到了零。

【问题讨论】:

    标签: java multithreading collections


    【解决方案1】:

    我猜你可以尝试使用执行平台特定的命令,例如将列表命令输出重定向到临时文件并使用 Java File API 读取它。

    ls > temp.txt

    我创建了一个简单的 shell 脚本,它将列出给定索引中的文件。

    #!/bin/bash
    
    RANGE_UP=$2
    RANGE_BOT=$1
    
    CURRENT_CNTR=0
    
    FILENAME=._m_ls
    
    ls -w 1 > $FILENAME
    while read line
    do
        if [ $CURRENT_CNTR -le $RANGE_UP -a $CURRENT_CNTR -gt $RANGE_BOT ]; then
        printf $line"\n"
        fi
        CURRENT_CNTR=`expr $CURRENT_CNTR + 1`
    done < $FILENAME
    

    您现在可以执行./ls_range.sh 10000 30000 &gt;temp.txt 之类的操作,然后在另一个线程中使用BufferedReader 从该文件中读取。

    【讨论】:

      【解决方案2】:

      您可以使用 FileUtils IOFileFilter。

      Collection<File> listFiles = FileUtils.listFiles(new File("."), counter, FileFilterUtils.trueFileFilter());
      

      counter 会在哪里

      IOFileFilter counter = new IOFileFilter() {
      
          @Override
          public boolean accept(File arg0, String arg1) {
              countCall();
              return true;
          }
      
          @Override
          public boolean accept(File arg0) {
              countCall();
              return true;
          }
      };
      

      countCall 是更新进度的方法。

      【讨论】:

      • 这个很有创意。我会尝试并回复你
      【解决方案3】:

      您执行此操作的唯一方法(与 java7 或之前建议的拆分工作相反)是编写自己的代码以在更新回调时搜索文件系统。

      我使用了来自commons-io 的代码,并对其进行了修改以满足您的需求,显然它需要测试,但它会在找到文件时对其进行计数。

      示例

      interface Counter {
          void foundFile(File file);
      }
      
      final class FileSearcher {
          public static Collection<File> listFiles(File root, FileFilter filter, Counter counter) {
              Collection<File> files = new ArrayList<File>();
              File[] found = root.listFiles(filter);
      
              if (found != null) {
                  for (int i = 0; i < found.length; i++) {
                      if (found[i].isDirectory()) {
                          files.addAll(listFiles(found[i], filter, counter));
                      } else {
                          files.add(found[i]);
                          counter.foundFile(found[i]);
                      }
                  }
              }
      
              return files;
          }
      }
      

      然后像这样使用它:

      final AtomicInteger inte = new AtomicInteger(0);
      FileSearcher.listFiles(new File("C:/"), null, new Counter() {
          @Override
          public void foundFile(File file) {
              System.out.println("found file number " + inte.addAndGet(1));
          }
      });
      

      【讨论】:

        【解决方案4】:

        在您从该方法获得返回值之前,您将无法访问填充的集合,因为您无权访问该方法在内部使用的变量。

        您可以通过不使用递归标志将搜索分成更小的部分,并自己处理递归以接收每个目录的集合。

        如果您使用的是 Java 7,更好的选择是使用 the FileVisitor interface to explore the file system。它有一些回调方法可以让您跟踪进度。

        【讨论】:

        • 不幸的是,我必须使用 Java 6,因为该应用程序需要在带有内置 JVM 的 Mac 上运行(Apple 仍然提供 Java 6!)
        • @Redandwhite 我认为您唯一的选择是拆分搜索 - 除非其他人有更好的主意。
        猜你喜欢
        • 2019-07-31
        • 1970-01-01
        • 1970-01-01
        • 2010-10-25
        • 2013-03-27
        • 2022-01-15
        • 2012-12-08
        • 2022-01-04
        相关资源
        最近更新 更多