Let's play Find that File
Bug

In the constructor, matchingRegex must be initialized before calling getAllFiles(root);, otherwise a NullPointerException is thrown if the root folder contains subfolders.

Design

Constructor

I agree with @holroy about the fact that there are too many things done in the constructor. Its job is too heavy, instead of just initialize some things. Moreover, it makes the FileFinder instance unusable for other parameters, e.g. to search in another folder or with another regex, one will need to instantiate a new FileFinder.

getAllFiles(File)

It should be named getAllMatchingFiles, because in the current implementation it returns only the files with names matching the regex and all the directories. By the way, it is not very clear why the directories are put there.

The implementation of this method is correct in general, but is coded entirely with before-Java-7 style. Indeed, java.nio would be a lot of help here.

First of all, there is FileVisitor interface. Using a SimpleFileVisitor prevents us from pre-calculating Map&lt;String, File&gt; files. It also solves the problem of files with same names in different folders:

public Collection&lt;Path&gt; findFiles(String fileName) throws IOException {
  final Collection&lt;Path&gt; foundFiles = new ArrayList&lt;&gt;();
  Files.walkFileTree(this.root.toPath(), 
                     new SimpleFileVisitor&lt;Path&gt;() {
      @Override
      public FileVisitResult visitFile(Path file, BasicFileAttributes attrs)
                throws IOException {
        if (file.getFileName().toString().equals(fileName)) {
            foundFiles.add(file);
        }
        return FileVisitResult.CONTINUE;
      }
    });
  return foundFiles;
}


This implementation will return all the files having fileName. If you want to get them by regex, it's achieved with a little change in the if condition.

If we push a bit deeper and try to benefit from Java 8, it becomes really concise:

public Collection&lt;Path&gt; findFiles8(String fileName) throws IOException {
  return Files.find(this.root.toPath(), 
                    Integer.MAX_VALUE, // NB! should be more reasonable :)
                    (file, attrs) -&gt; {
         return Files.isRegularFile(file) 
           &amp;&amp; file.getFileName().toString().equals(fileName);
    }).collect(Collectors.toList());
}


In fact, Files.find(args) can do almost all the job of FileFinder...

copy(args)

I think that this method should be defined elsewhere, because it does not correspond to the functionality of FileFinder.

It's a good idea to use Files.copy() inside it (and even better would be instead of it). Since this is a public method, the validation of the arguments should be done on non-nullability of file and dest. The existence of the files will be checked in Files.copy(), with the respective exceptions thrown.

The target Path object can be created easier with dest.toPath().resolve(file.getName()), no need to instantiate a File.