import java.nio.file.Path;
import java.nio.file.Paths;
import java.nio.file.Files;
import java.nio.file.DirectoryStream;
import java.util.HashMap;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;

public class WordCount {
    public static void main(String[] args) throws Exception {
        HashMap<String, Integer> record = new HashMap<String, Integer>(); // store count in map
        String path = "../testdata";
        Path dataDir = Paths.get(path); // get directory info
        DirectoryStream<Path> files = Files.newDirectoryStream(dataDir);
        for (Path file : files) {
            if (Files.isDirectory(file)) {
                continue;
            }
            String text = new String(Files.readAllBytes(dataDir.resolve(file.getFileName()))); // read file content
            String word = new String("");
            for (int i = 0; i < text.length(); i++) {
                if (Character.isLetter(text.charAt(i)) || word.length() > 0 && text.charAt(i) == '\'') {
                    word += Character.toLowerCase(text.charAt(i)); // extend word
                } else if (word.length() > 0) {
                    record.put(word, record.getOrDefault(word, 0) + 1); // update map
                    word = "";
                }
            }
            if (word.length() > 0) {
                record.put(word, record.getOrDefault(word, 0) + 1); // update map
            }
        }
        ArrayList<HashMap.Entry<String, Integer>> list = new ArrayList<HashMap.Entry<String, Integer>>(record.entrySet()); // get answer from map
        Collections.sort(list, new Comparator<HashMap.Entry<String, Integer>>() {
            public int compare(HashMap.Entry<String, Integer> o1, HashMap.Entry<String, Integer> o2) { // compare function
                if (o1.getValue().equals(o2.getValue())) {
                    return o1.getKey().compareTo(o2.getKey());
                }
                return o1.getValue() < o2.getValue() ? 1 : -1;
            }
        });
        for (HashMap.Entry<String, Integer> itr : list) {
            System.out.printf("%s\t%d\n", itr.getKey(), itr.getValue());
        }
    }
}
