Как записать данные из HashMap в файл в отсортированном порядке с потоками

Я могу вывести отсортированные записи из HashMap следующим образом:

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"));
}

Но теперь мне нужно записывать записи в файл. Я делаю это:

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();
}

Отображается ошибка:

Unhandled exception: java.io.IOException.

Как вывести отсортированные записи из HashMap в файл?

сначала отсортируйте карту, а затем повторите запись в файл

bhaskarkh 21.03.2022 13:17

Эта ошибка связана с файловыми операциями, которые вы пытаетесь выполнить, что может привести к исключению IOException, и вам необходимо с этим справиться. Это либо обрабатывается путем выполнения try-catch (или try-with-resources), либо путем выдачи исключения вызывающему методу. Какой из них зависит от того, как вы хотите обработать исключение.

DanielBarbarian 21.03.2022 13:18

Также видя, что вы на самом деле имеете свой код в попытке, вы можете просто добавить улов к этой попытке.

DanielBarbarian 21.03.2022 13:19
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
В компьютерном программировании биты играют важнейшую роль в представлении и манипулировании данными на двоичном уровне. Побитовые операции...
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Приходилось ли вам сталкиваться с требованиями, в которых вас могли попросить поднять тревогу или выдать ошибку, когда метод Java занимает больше...
Полный курс Java для разработчиков веб-сайтов и приложений
Полный курс Java для разработчиков веб-сайтов и приложений
Получите сертификат Java Web и Application Developer, используя наш курс.
1
3
64
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Обработайте исключение при записи fw.write(x + "ms"); в файл, см. код ниже. Функция FileWriter запись показывает Исключение ввода-вывода, которые вы не обрабатывали.

try {
            File file = new File("newfile.txt");
            if (!file.exists())
                file.createNewFile();
            FileWriter fw = new FileWriter(file, true);
            noSortedMap.entrySet().stream()
                    .sorted(Map.Entry.<String, Integer>comparingByValue().reversed())
                    .forEach(x -> {
                        try {
                            fw.write(x + "ms");
                        } catch (IOException e) {
                            e.printStackTrace();
                        }
                    });
            fw.write("---" + new Date() + "\n");
            fw.close();
        }
        catch (Exception e)
        {
            System.out.println("Exception occur emsg= "+w.getMessage());
        }
Ответ принят как подходящий

Размещение IO-операции подобно записи в файл — это не хорошая идея, потому что код обработки исключений полностью исключает читабельность лямбда-выражений.

Основная причина, по которой функциональное программирование было введено в Java, заключается в том, чтобы обеспечить лучший способ из структурирование кода, циклы всегда больше исполнитель, чем последовательные потоки.

Я предлагаю решить эту проблему в два отдельных шага: сначала подготовить данные, а затем записать их в файл.

Подготовка данных повлечет за собой:

  • сортировка содержимое карты;
  • преобразование каждой записи в String и добавление единицы времени "ms";
  • сбор отсортированных данных в список.

первый шаг может выглядеть так:

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());
}

Запись в файл (для лучшей производительности FileWriter заключен в 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();
    }
}

А с Java НИО второй шаг можно упростить до:

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();
    }
}

Пара важных замечаний:

  • Никогда закрывает ресурсы внутри блока try, если возникает исключение, ресурс никогда не будет освобожден. Для этого можно либо использовать попробуй с ресурсами (что является предпочтительным способом), либо явно вызывать close() в блоке finally.

  • Использование операции forEach()обескуражен документацией в ситуациях, когда есть альтернативный способ добиться того же результата. Таким образом, подход записи в файл из потока — это плохой по всем пунктам:

    - осуждает удобочитаемость;

    - делает ваш метод менее узконаправленный и сложнее проверить;

    - это не согласовано с документацией.

Другие вопросы по теме