Отсортировать и форматировать вывод из Map()

227
15 февраля 2022, 01:20

Есть метод:

public void ShowRacingResults(String folderPath) {
    Map<String, String> abbreviationsMap = ConvertFileToMap(folderPath + "/abbreviations.txt");
    Map<String, String> resultMap = CalculateResults(folderPath);
    int place = 1;
    for (String s : resultMap.keySet())
        for (String k : abbreviationsMap.keySet())
            if (s.equals(k)) {
                System.out.println(place + ". " + abbreviationsMap.get(k).split("_")[0] + " | "
                        + abbreviationsMap.get(k).split("_")[1] + " | " + resultMap.get(s));
                place++;
            } else if (s.equals(k) & place == 16) {
                System.out.println("------------------------------------------------------------------------"
                        + "\n" + place + ". " + abbreviationsMap.get(k).split("_")[1] + " | "
                        + abbreviationsMap.get(k).split("_")[2] + " | " + resultMap.get(s));
                place++;
            }
}

Который в итоге выводит результаты в виде:

  1. Valtteri Bottas | MERCEDES | 1:12.434
  2. Sebastian Vettel | FERRARI | 1:04.415
  3. Carlos Sainz | RENAULT | 1:12.950
  4. Daniel Ricciardo | RED BULL RACING TAG HEUER | 1:12.013
  5. Kevin Magnussen | HAAS FERRARI | 1:13.393
  6. Sergio Perez | FORCE INDIA MERCEDES | 1:12.848
  7. Stoffel Vandoorne | MCLAREN RENAULT | 1:12.463
  8. Charles Leclerc | SAUBER FERRARI | 1:12.829
  9. Brendon Hartley | SCUDERIA TORO ROSSO HONDA | 1:13.179
  10. Lewis Hamilton | MERCEDES | 1:12.460
  11. Lance Stroll | WILLIAMS MERCEDES | 1:13.323
  12. Romain Grosjean | HAAS FERRARI | 1:12.930
  13. Fernando Alonso | MCLAREN RENAULT | 1:12.657
  14. Sergey Sirotkin | WILLIAMS MERCEDES | 1:12.706
  15. Nico Hulkenberg | RENAULT | 1:13.065
  16. Marcus Ericsson | SAUBER FERRARI | 1:13.265
  17. Esteban Ocon | FORCE INDIA MERCEDES | 1:13.028
  18. Pierre Gasly | SCUDERIA TORO ROSSO HONDA | 1:12.941
  19. Kimi Raikkonen | FERRARI | 1:12.639

Подскажите пожалуйста как сделать чтобы результаты выводились с отсортированным временем и имели вид типа:

Answer 1

Как уже и говорил, такие данные лучше сначала распарсить и привести в адекватный вид. Посему для данных создадим класс Person, в нем три соответсвующих поля. Сначала создаем экземпляры данного класса, складываем их в коллекцию, теперь мы можете сделать с ними все, что хотите. Для сортировки по дате пишем простенький класс-компаратор и вызываем метод сортировки у коллекции. Когда нам нужна еще одна сортировки, пишем еще один компаратор с любой логикой. Таким образом, вы очень упрощаете дальнейшее расширение программы. Единственный момент - вы не ответили про формат времени. Посему парсер самого времени оптимизируйте уже сами.

import java.time.LocalTime;
import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
public class Person {
    private final static DateTimeFormatter FORMATTER = DateTimeFormatter.ofPattern("mm:ss.SSS");
    private final String name;
    private final String modelAuto;
    private final LocalTime time;
    public Person(String name, String modelAuto, String time) {
        this.name = name;
        this.modelAuto = modelAuto;
        int msPoint = time.indexOf("."), sPoint = time.indexOf(":");        
        this.time= LocalTime.of(0, parseInt(time, 0, sPoint), 
                parseInt(time, sPoint+1, msPoint), parseInt(time, msPoint+1, time.length())*1_000_000);
    }    
    private int parseInt(String time, int start, int end){
        return Integer.valueOf(time.substring(start, end));
    }
    public String getName() {
        return name;
    }
    public String getModelAuto() {
        return modelAuto;
    }
    public LocalTime getTime() {
        return time;
    }
    @Override
    public String toString() {
        return name + " | " + modelAuto + " | " + FORMATTER.format(time);
    }
    public static List<Person> parse(Map<String, String> abbreviationsMap, Map<String, String> resultMap) {
        final List <Person> persons = new ArrayList<>();
        int place = 1;
        for (String s : resultMap.keySet()) {
            for (String k : abbreviationsMap.keySet()) {
                if (s.equals(k)) {
                    String[] split = abbreviationsMap.get(k).split("_");
                    persons.add(new Person(split[0], split[1], resultMap.get(s)));
                    place++;
                } else if (s.equals(k) & place == 16) {
                    String[] split = abbreviationsMap.get(k).split("_");
                    persons.add(new Person(split[1], split[2], resultMap.get(s)));
                    place++;
                }
            }
        }
        persons.sort(new PersonTimeComparator());  
        return persons;
    }
}

import java.util.Comparator;
public class PersonTimeComparator implements Comparator<Person> {
    @Override
    public int compare(Person p1, Person p2) {
        return p1.getTime().compareTo(p2.getTime());
    }
}
Answer 2

Сортировку я провел, код ниже(метод CalculateResults, которого я не представил для обозрения теперь возвращает LinkedList). Остается вопрос с форматом вывода(разграничители "|" нужно выставить по уровню и после 15го гонщика должен быть разделитель "-----").

Map<String, String> resultMap = CalculateResults(folderPath)
            .stream()
            .collect(Collectors.toMap(k -> k.substring(0,3), v -> v.substring(7)))
            .entrySet()
            .stream()
            .sorted(Map.Entry.<String, String>comparingByValue()) //TODO sorting racers by time
            .collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue, (e1, e2) -> e1, LinkedHashMap::new));
READ ALSO
Android калькулятор не работает

Android калькулятор не работает

Написал я простенький калькулятор с вычислением процентовНекоторые числа он обрабатывает нормально и все выводит туда куда нужно

138
Нужно ли указывать final для всех переменных которые не изменяются?

Нужно ли указывать final для всех переменных которые не изменяются?

В книгах о Java написано, что если переменная не будет изменятся, то нужно указывать модификатор finalНо получается, что тогда этот модификатор...

288
dynamic binding

dynamic binding

читаю "Философию Java" ЭккеляКак-то к сожалению он сложно описывает некоторые моменты, и один из таких: Динамическое связывание

161