javahashmapjava-streamjava-iofilewriter

How to write the data from a HashMap into a file in Sorted order with Streams


I can output sorted entries from a HashMap like this:

public static void sortAverageTime(HashMap<String, Integer> noSortedMap) {
    noSortedMap.entrySet().stream()
            .sorted(Map.Entry.<String, Integer>comparingByValue().reversed())
            .forEach(x -> System.out.println(x + "ms"));
}

But now I need to write the entries into a file. I'm doing this:

try {
    File file = new File("newfile.txt");
    if (!file.exists())
        file.createNewFile();
    FileWriter fw = new FileWriter(file, true);
    averageTime.entrySet().stream()
                          .sorted(Map.Entry.<String, Integer>comparingByValue().reversed())
                          .forEach(x -> fw.write(x + "ms"));
    fw.write("---" + currentDate + "\n");
    fw.close();
}

An error is displayed:

Unhandled exception: java.io.IOException.

How can I output sorted entries from a HashMap to a file?


Solution

  • Placing IO-operations like writing to a file is not a good idea because exception-handling plumbing code completely defeats the readability of lambda expressions.

    The primary reason why function programming was introduced in Java is to provide the better way of structuring the code, loops are always more performant than sequential streams.

    I suggest to address this problem in two separate steps: first, prepare the data and then write it into a file.

    Preparing the data will entail:

    The first step might look like this:

    public static List<String> getSortedData(Map<String, Integer> averageTime) {
        return averageTime.entrySet().stream()
                .sorted(Map.Entry.<String, Integer>comparingByValue().reversed())
                .map(entry -> String.format("%s %d %s", entry.getKey(), entry.getValue(), "ms"))
                .collect(Collectors.toList());
    }
    

    Writing to a file (for better performance FileWriter is wrapped into a BufferedWriter)

    public static void sortAverageTime(Map<String, Integer> averageTime,
                                       String fileName) {
        File file = new File(fileName);
        if (!file.exists())
            file.createNewFile();
    
        List<String> sortedData = getSortedData(averageTime);
        sortedData.add("---" + LocalDate.now()); // replacement for fw.write("---" + currentDate + "\n")
        try(BufferedWriter writer = new BufferedWriter(new FileWriter(file, true))) {
            for (String next: sortedData) {
                writer.write(next);
                writer.newLine();
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
    

    And with Java NIO the second step could be simplified to:

    public static void sortAverageTime(Map<String, Integer> averageTime,
                                       String fileName) {
        File file = new File(fileName);
        if (!file.exists())
            file.createNewFile();
    
        List<String> sortedData = getSortedData(averageTime);
        sortedData.add("---" + LocalDate.now());
        try {
            Files.write(file.toPath(), sortedData, StandardOpenOption.APPEND);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
    

    A couple of important notes: