Improved 


Ken Birman
​
Ken Birman​
import java.io.*;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.CountDownLatch;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.stream.Stream;

public class Main {
    record Entry(String name, int count) {}

    static Pattern pattern = Pattern.compile("[a-zA-Z_][0-9a-zA-Z_]*");
    static ConcurrentHashMap<String, Integer> counts = new ConcurrentHashMap<>();

    public static void main(String[] args) throws InterruptedException {
        int argind = 0;
        if (args.length >= 1 && args[0].equals("--profile")) {
            argind++;
            System.err.print("Waiting for input.");
            try { System.in.read(); } catch (Exception e) {}
        }
        if (argind >= args.length) {
            System.err.println("Usage: wc++ [--profile] <dir>");
            System.exit(2);
        }
//      System.err.println("Reading files");
        Thread.Builder builder = Thread.ofVirtual();
        try (Stream<Path> files = Files.walk(Path.of(args[argind]))
                .filter(path -> path.getFileName().toString().endsWith(".c") ||
                                path.getFileName().toString().endsWith(".h"));
             Writer writer = new BufferedWriter(new OutputStreamWriter(System.out), 1<<16)) {
            List<Path> filenames = files.toList();
            CountDownLatch latch = new CountDownLatch(filenames.size());
            for (Path f : filenames) {
                builder.start(() -> countWords(f, latch));
            }
            latch.await();
//          System.err.println("Building array of entries");
            Entry[] entries = counts.entrySet().stream()
                    .map(e -> new Entry(e.getKey(), e.getValue()))
                    .toArray(Entry[]::new);
//          System.err.println("Sorting entries");
            Arrays.parallelSort(entries,
                    Comparator.comparingInt(Entry::count).reversed()
                              .thenComparing(Entry::name));
//          System.err.println("Printing entries");
            for (Entry entry : entries) {
                writer.write(entry.name);
                writer.write(": ");
                writer.write(entry.count);
                writer.write('\n');
            }
        } catch (FileNotFoundException e) {
            System.err.println("Could not read file list");
            System.exit(1);
        } catch (IOException e) {
            System.err.println("I/O Exception");
            System.exit(1);
        }
    }

    private static void countWords(Path f, CountDownLatch latch) {
        try {
            String content = Files.readString(f, StandardCharsets.ISO_8859_1);
            Matcher matcher = pattern.matcher(content);
            while (matcher.find()) {
                counts.merge(matcher.group(), 1, Integer::sum);
            }
            latch.countDown();
        } catch (FileNotFoundException e) {
            System.err.println("Warning: could not open file " + f);
        } catch (IOException e) {
            System.err.println("File " + f + ": IO exception " + e);
        }
    }
}