Javaで指定したディレクトリ以下にある指定した拡張子を持ったファイルをリストに保存する方法

## 背景
多数のファイルに対してJavaで操作が必要な時に、ターミナルの`find`コマンドなどでリストアップしてからJavaに渡すよりも、リストアップの部分もJavaで実装したほうが、処理が一貫して簡単なのでこのコードを書いた。

## コードの概要
このプログラムは、ディレクトリ名と拡張子を引数として、指定したディレクトリとそれより下層のディレクトリを探索し、指定した拡張子のファイルを`ArrayList`に保存する。ここではiTunesのフォルダにあるm4aファイルを探して、リストに保存する。

上のコードではJava8で新しく導入されたラムダ式(`Lambda Expressions`)とストリーム(`Stream`)を使っている。ラムダ式とストリームを使っていないコードは下を参照。（Java8より古いJavaでも動くかも。。）


### Java 8以降
```java
import java.io.File;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.regex.Pattern;
import java.util.ArrayList;
import java.util.stream.Stream;

public class Utils {
    public static void main(String[] args) throws IOException {
        // To list up m4a files in iTunes directory
        Path rootDir = Paths.get(System.getProperty("user.home"), "Music", "iTunes");
        String extension  = "m4a";

        // for standard inputs
        if (args.length == 2) {
            rootDir = Paths.get(args[0]);
            extension   = args[1];
        } else if (args.length != 0){
            System.err.println("Error: set correct args.");
        }

        if (!Pattern.matches("^[0-9a-zA-Z]+$", extension)) {
            System.err.println("Error: set correct extension. (only alphabet and numeric)");
        } else {
            ArrayList<File> fileList = listUpFiles(rootDir, extension);
            for (File file : fileList) {
                System.out.println(file.getAbsolutePath());
            }
            System.out.println(fileList.size());    
        }
    }

    /**
     * list up files with specified file extension (extension)
     * under the specified directory (rootDir) recursively.
     * @param rootDir   : root directory
     * @param extension : string needs to be contained as file extension
     * @return          : list of files
     */
     public static ArrayList<File> listUpFiles(Path rootDir, String extension){
        String extensionPattern = "." + extension.toLowerCase();
        final ArrayList<File> fileList = new ArrayList();

        try (final Stream<Path> pathStream = Files.walk(rootDir)) {
            pathStream
                    .map(path -> Path::toFile)
                    .filter(file -> !file.isDirectory())
                    .filter(file -> file.getName().toLowerCase().endsWith(extensionPattern))
                    .forEach(fileList::add);
        } catch (final IOException e) {
            e.printStackTrace();
        }
        return (fileList);
    }
}
```

### ラムダ式とストリームを使っていないコード

```Java
import java.io.File;
import java.util.regex.Pattern;
import java.util.ArrayList;

public class UtilsOld {

    public static void main(String[] args) {
        // To list up m4a files in iTunes directory
        String rootDirName = System.getProperty("user.home") + java.io.File.separator +
                             "Music" + java.io.File.separator + "iTunes";
        String extension  = "m4a";

        // for standard input
        if (args.length == 2) {
            rootDirName = args[0];
            extension   = args[1];
        } else if (args.length != 0){
            System.err.println("Error: set correct args.");
        }

        if (!Pattern.matches("^[0-9a-zA-Z]+$", extension)) {
            System.err.println("Error: set correct extension. (only alphabet and numeric)");
        } else {
            String extensionPattern = "." + extension.toLowerCase();

            ArrayList<File> fileList = new ArrayList();
            fileList = listUpFiles(rootDirName, extensionPattern, fileList);

            for (File file : fileList) {
                System.out.println(file.getAbsolutePath());
            }
            System.out.println(fileList.size());
        }
    }

    /**
     * list up files with specified file extension (ext)
     * under the specified directory (rootDirName) recursively.
     *
     * @param rootDirName      : root directory name
     * @param extensionPattern : regular expression pattern of file extension
     * @param fileArrayList    : ArrayList to store files
     * @return : return fileArrayList
     */
    public static ArrayList listUpFiles(String rootDirName, String extensionPattern, ArrayList<File> fileArrayList){
        File rootDir = new File(rootDirName);
        File[] listOfFiles = rootDir.listFiles();
        assert listOfFiles != null;

        for (File item : listOfFiles) {
            if (item.isDirectory()) {
                fileArrayList = listUpFiles(item.getAbsolutePath(), extensionPattern, fileArrayList);
            } else if (item.isFile()) {
                String fileName = item.getName().toLowerCase();
                if (fileName.endsWith(extensionPattern)) {
                    fileArrayList.add(item);
                }
            }
        }
        return(fileArrayList);
    }
}

``` 

## 参考
saka1029さんのコメント
https://www.javacodegeeks.com/2014/05/playing-with-java-8-lambdas-paths-and-files.html