Efficient File Searching
Comments about your current code first:

Closing the Stream

The method Files.lines(path) returns a Stream&lt;String&gt; over the lines of the file. This stream should be closed because it encapsulates a Reader of the file. The documentation mentions that:


  If timely disposal of file system resources is required, the try-with-resources construct should be used to ensure that the stream's close method is invoked after the stream operations are completed.


Therefore, the method populateWordMap should be using a try-with-resources:

try (Stream&lt;String&gt; stream = Files.lines(Paths.get(filePath))) {
    // ...
}


Allocating unused objects

You currently allocate the wordMap with a new hash map, and then store the result of invoking populateWordMap in it.

Map&lt;String, Long&gt; wordMap = new HashMap&lt;&gt;();
try {
    wordMap = populateWordMap("C:\\Outils\\eclipse-mars\\workspace\\test\\text.txt");


The consequence is that the first hash map that was created for nothing: it is unused and will be garbage collected. Best not to create it in the first place.

Empty catch blocks

try {
    // something
} catch(IOException e) { }


is generally not a good idea: you are completely swallowing the exception that could be thrown and giving no information. You could log the exception to tell what went wrong; you could also rethrow it; or you could even let the main method throw it, since there is really nothing you can do at this level when something wrong happens.

Handling empty Optional

Your findMostPopularWord method is searching for the word appearing the most times. It works by correctly using the max operation. But then, you have:

.max(Map.Entry.comparingByValue()).get().getKey();


To get the key of the entry having the max value. The problem is that when the Stream is empty, max will return an empty Optional and the explicit call to .get() will throw an exception. This raises the more general question of what you want to happen where the scanned file is empty (and contains no words). Among the possible solutions: just return null or throw a custom exception. For those two solutions, you can use .orElse(null) or orElseThrow(...), instead of get.

Looping over all files in a directory

I'll note that your current solution only works by counting word occurences in a single file when the original task was to do it for all files in a directory. For that enhancement, you can use Files.list(path) which returns a Stream&lt;Path&gt; of all the files under the given path.



The current flow of your code is:


Loop over each line of the file
Split each line in an array of words
Replace each array of words with a map containing the occurrences of each word
Replace each of those map with another map containing the occurrences of each entry's value.


This is not very efficient: you are converting each line into a map, only to disregard them later and create another map out of all those maps.

The problem is that you're thinking in terms of "line in a file" when the actual task is to count space separated words. For this task, you can use a Scanner:

private static Map&lt;String, Long&gt; populateWordMap(String filePath) throws IOException {
    try (Scanner scanner = new Scanner(Paths.get(filePath))) {
        Iterable&lt;String&gt; iterable = () -&gt; scanner;
        return StreamSupport.stream(iterable.spliterator(), false)
                     .collect(Collectors.groupingBy(Function.identity(), Collectors.counting()));
    }
}


A scanner tokenize by default around single spaces. We can then convert the scanner (which is an Iterator) to a Stream and group by each word while counting their occurences.