Частота отсчета элементов в java - PullRequest
0 голосов
/ 03 марта 2020

Я пытаюсь посчитать частоту всех дат из текстового файла. Даты сохраняются в parsed.get (0), но когда я печатаю частоту, я получаю этот вывод:

1946-01-12: 1
1946-01-12: 1
1946-01-12: 1
1946-01-13: 1
1946-01-13: 1
1946-01-13: 1
1946-01-14: 1
1946-01-14: 1
1946-01-14: 1
1946-01-15: 1

вместо

1946-01-12: 3
1946-01-13: 3
1946-01-14: 3
1946-01-15: 1

Я думаю, это потому, что я должен хранить даты как ("1946-01-12", "1946-01-12", "1946-01-12", "1946-01-12", "1946-01-13", "1946-01- 13" , ...). Если я просто напечатаю parsed.get (0), я получу

1946-01-12
1946-01-12
1946-01-12
1946-01-13
1946-01-13
1946-01-13
1946-01-14
1946-01-14
1946-01-14
1946-01-15`

Как я могу решить эту проблему, основываясь на моем коде ниже?

private static List<WeatherDataHandler> weatherData = new ArrayList<>();
public void loadData(String filePath) throws IOException {

//Read all data
    List<String> fileData = Files.readAllLines(Paths.get("filePath"));
    System.out.println(fileData);

    for(String str : fileData) {
        List<String> parsed = parseData(str);
        LocalDate dateTime = LocalDate.parse(parsed.get(0));

        WeatherDataHandler weather = new WeatherDataHandler(dateTime, Time, temperature, tag);
        weatherData.add(weather);

        List<String> list = Arrays.asList(parsed.get(0));

        Map<String, Long> frequencyMap =
                list.stream().collect(Collectors.groupingBy(Function.identity(), 
                                                        Collectors.counting()));

            for (Map.Entry<String, Long> entry : frequencyMap.entrySet()) {
                System.out.println(entry.getKey() + ": " + entry.getValue());
            }
    }

Ответы [ 4 ]

2 голосов
/ 03 марта 2020

Проблема

Все, что находится внутри for-l oop, выполняется на каждой итерации . Таким образом, вы воссоздаете свою коллекцию дат и воссоздаете поток для анализа снова и снова. Фигово.

Решение

Переместите поток и код анализа за пределы for-l oop.

Переосмыслите ваш код как две фазы.

  • Первый этап - анализ входных данных, предварительная обработка входящих данных в форму, с которой вы хотите работать. В этом случае нам нужно прочитать текстовый файл, разобрать строки в LocalDate объектах и ​​добавить эти объекты в коллекцию. В этом коде используется for-l oop.
  • . Второй этап - потоковая работа для обработки преобразованных данных, сбора объектов LocalDate. Этот код приходит после for-l oop.

В моей собственной работе я буквально поместил бы эти маркеры в своем коде как комментарии. И я бы добавил разделительные линии (строки комментариев с кучей комментариев или обычными знаками), чтобы отметить каждую фазу в коде. И я мог бы переместить каждую фазу в метод как подпрограмму.

Кстати, как только вы получите его работу, для забавы вы можете попробовать заменить for-l oop чтение файла потоком , Java может прочитать файл как поток строк.

0 голосов
/ 03 марта 2020

Исходя из того, как я думаю, что это работает, я сделал бы это следующим образом. Комментарии включены, чтобы объяснить дополнительные логи c. Основная идея - сделать как можно больше внутри вашего основного l oop. Создание frequenceyMap вне l oop с помощью stream является дополнительной и ненужной работой.

    private static List<WeatherDataHandler> weatherData =
            new ArrayList<>();

    public void loadData(String filePath) throws IOException {

        // Read all data
        List<String> fileData =
                Files.readAllLines(Paths.get("filePath"));
        System.out.println(fileData);

        // Pre-instantiate the freqency map.
        Map<String, Long> frequencyMap = new LinkedHashMap<>();

        for (String str : fileData) {

            List<String> parsed = parseData(str);

            LocalDate dateTime =
                    LocalDate.parse(parsed.get(0));

            WeatherDataHandler weather = new WeatherDataHandler(
                    dateTime, Time, temperature, tag);
            weatherData.add(weather);

            // Ensure dateTime is a string.  This may not have the desired
            // format for date but that can be corrected by you
            String strDate = dateTime.toString();

            // Use the compute method of Map. If the count is null,
            // initialize it to 1, otherwise, add 1 to the existing value.
            frequencyMap.compute(strDate,
                    (date, count) -> count == null ? 1 : count + 1);
        }

        for (Map.Entry<String, Long> entry : frequencyMap
                .entrySet()) {
            System.out.println(
                    entry.getKey() + ": " + entry.getValue());
        }
    }

Вы также можете распечатать карту следующим образом:

frequencyMap.forEach((k,v)->System.out.println(k + ": " + v));

Наконец вышеописанное можно было бы упростить в нескольких местах, например, используя Files.lines(path) для создания потока. Но так как вы также записываете это в список WeatherDataHandler и хотите сохранить свою структуру, я не использовал эту функцию.

0 голосов
/ 03 марта 2020

При этом вы можете получить количество элементов с одинаковым значением в вашем списке.

int numerOfElements = Collections.frequency(list, "1946-01-12");
0 голосов
/ 03 марта 2020

Я проверил этот кратко, вы можете проверить результат

{1946-01-14=3, 1946-01-15=1, 1946-01-12=3, 1946-01-13=3}

исходный файл был

1946-01-12: 1
1946-01-12: 1
1946-01-12: 1
1946-01-13: 1
1946-01-13: 1
1946-01-13: 1
1946-01-14: 1
1946-01-14: 1
1946-01-14: 1
1946-01-15: 1

изменить его так, как вам нравится

код:

 try {
            String content = new Scanner(new File("src/main/resources/test.txt")).useDelimiter("\\Z").next();
            String[] dates=  content.split("\\n");
            Map<String,Long> m
                    =
                    Arrays.stream(dates).
                            map(o->
                            {return o.split(":")[0];}) //not necessary if you dont have 1s in the text file
                            .collect(Collectors.groupingBy(Function.identity(), Collectors.counting()));

            System.out.println(m.toString());
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        }
...