Sortowanie tablicy obiektów

0

Mam zadanie gdzie do posortowania jest tablica obiektów klasy Event, która to ma 2 pola String. Jednym z nich jest Data i to po niej będziemy sortować. W zadaniu zaznaczono, że nie można korzystać z typów do przechowywania daty i czasu i z kolekcji. Tylko tablice.
Mój pomysł jest prosty w zamyśle: sortuje najpierw po roku, później po miesiącach i po dniach. Na razie napisałem tylko sortowanie po roku. Zanim przejdę dalej może podsuniecie pomysł jak zrobić to w bardziej elegancki sposób bo moje rozwiązanie nie podoba mi się w ogóle. A oto moje wypociny:


    public static void sortEvent(Event[] events) {

        Event[] sortedEventList = new Event[events.length];
        Event[] unSortedEventList = new Event[events.length];

        //searching first year
        int index = 0;
        if (!allYearsIsTheSame(events)) {
            for (int i = 0; i < events.length; i++) {

                sortedEventList[i] = events[findMinYer(events)];
                index = 0;
                for (int j = 0; j < events.length; j++) {
                    if (j != findMinYer(events)) {
                        unSortedEventList[index] = events[j];
                        index++;
                    }
                }
                events = Arrays.copyOf(unSortedEventList, unSortedEventList.length);
            }
            System.out.println("sorted List: " + Arrays.toString(sortedEventList));

            }
        }


    static int findMinYer(Event[] events) {

        int year = Integer.MAX_VALUE;
        final int yearIndex = 2;
        String[] date;
        int minYearIndex = 0;

        for (int i = 0; i < events.length; i++) {
            if(events[i] != null) {
                date = events[i].getEventDate().split("\\.");

                if (Integer.parseInt(date[yearIndex]) < year) {
                    year = Integer.parseInt(date[yearIndex]);
                    minYearIndex = i;
                }
            }
        }
        return minYearIndex;
    }


    public static boolean allYearsIsTheSame(Event[] events) {

        int year;
        final int yearIndex = 2;
        String[] date;

        for (int i = 0; i < events.length - 1; i++) {

            date = events[i].getEventDate().split("\\.");
            year = Integer.parseInt(date[yearIndex]);

            if (year != Integer.parseInt(events[i + 1].getEventDate().split("\\.")[yearIndex]))
                return false;
        }
        return true;
    }

0

java.util.Arrays.sort i własny comparator do eventow mieści się w dopuszczalnych rozwiązaniach?

1
manifestor napisał(a):

Mój pomysł jest prosty w zamyśle: sortuje najpierw po roku, później po miesiącach i po dniach. Na razie napisałem tylko sortowanie po roku.

To jest zły pomysł. Sortowanie ma być jedno, z trójpolowym porównywaniem. Nie wolno ci użyć gotowych klas, ale MyComparator trzeba zrobić, nawet i do 'ręcznego' sortowania

0

Wyszło tak:

Nadpisana metoda compareTo w klasie Event

    @Override
    public int compareTo(Event o2) {

        //Jeśli event o1 jest pierwszy to zwróć 1
        //Jeśli event jest tego samego dnia to zwróć 0
        //Jeśli event o2 jest pierwszy to zwróć 2

        String[] dateO1 = this.getEventDate().split("\\.");
        String[] dateO2 = o2.getEventDate().split("\\.");

        if (Integer.parseInt(dateO1[2]) == Integer.parseInt(dateO2[2])) {
            if (Integer.parseInt((dateO1[1])) == Integer.parseInt(dateO2[1])) {
                if (Integer.parseInt(dateO1[0]) == Integer.parseInt(dateO2[0])) {
                    return 0;
                } else if (Integer.parseInt(dateO1[0]) < Integer.parseInt(dateO2[0])) {
                    return 1;
                } else return 2;


            } else if (Integer.parseInt(dateO1[1]) < Integer.parseInt(dateO2[1])) {
                return 1;
            } else return 2;


        } else if (Integer.parseInt(dateO1[2]) < Integer.parseInt(dateO2[2])) {
            return 1;
        } else return 2;
    }

Klasa EventUtils


  public static void swapEvents(Event[] events, int i, int j) {
        Event tmpEvent = events[i];
        events[i] = events[j];
        events[j] = tmpEvent;
    }


    public static void sortEvent(Event[] events) {

        boolean change = false;

        do{
            change = false;
            for (int i = 0; i < events.length-1; i++) {
                for (int j = i + 1; j < events.length; j++) {
                    if (events[i].compareTo(events[j]) == 2) {
                        swapEvents(events, i, j);
                        change = true;
                        j = events.length;
                    }
                }
            }
        }while (change);

        System.out.println("Posortowane eventy: " + Arrays.toString(events));

    }

1
  1. Jest taki interfejs: https://docs.oracle.com/javase/8/docs/api/java/lang/Comparable.html, który ma metodę compreTo, która powinna zwracać "a negative integer, zero, or a positive integer as this object is less than, equal to, or greater than the specified object.".
  2. Jest coś takiego jak https://pl.wikipedia.org/wiki/Porządek_leksykograficzny - sprawdź jak zadziała Twoje compareTo, jak zredukujesz implementację do prymitywnego return this.getEvnetDate().compareTo(o2.getEventDate()); (prymitywnego, bo wywali się na Eventach, które nie mają ustawionej daty).
  3. Dlaczego nie użyjesz po prostu API do sortowania tablic ?
1
yarel napisał(a):
  1. Jest coś takiego jak https://pl.wikipedia.org/wiki/Porządek_leksykograficzny - sprawdź jak zadziała Twoje compareTo, jak zredukujesz implementację do prymitywnego return this.getEvnetDate().compareTo(o2.getEventDate()); (prymitywnego, bo wywali się na Eventach, które nie mają ustawionej daty).

A co innego można zrobić niż się wywalić. NullPointerException to twój przyjaciel.

Jak zaimplementują w Javie 14 ten ficzur - to NPE będzie jeszcze fajniejszy:
https://bugs.openjdk.java.net/browse/JDK-8218628

0
jarekr000000 napisał(a):
yarel napisał(a):
  1. Jest coś takiego jak https://pl.wikipedia.org/wiki/Porządek_leksykograficzny - sprawdź jak zadziała Twoje compareTo, jak zredukujesz implementację do prymitywnego return this.getEvnetDate().compareTo(o2.getEventDate()); (prymitywnego, bo wywali się na Eventach, które nie mają ustawionej daty).

A co innego można zrobić niż się wywalić. NullPointerException to twój przyjaciel.

Można mieć logikę sortowania NULLS FIRST/LAST. Co lepsiejsze, to już do osobnego rozważania dla konkretnego przypadku.

Jak zaimplementują w Javie 14 ten ficzur - to NPE będzie jeszcze fajniejszy:
https://bugs.openjdk.java.net/browse/JDK-8218628

Wietrzę "potężny" pattern wynikający z ficzera :D

catch (NullPointerException e) {
  if (e.getMessage().matches(...) ) { 
  } 
  ... 
  else { ... }

Dobrze, że Oracle pomyślał (-XX:ShowCodeDetailsInExceptionMessages) o zgodności wstecznej.

1

Walczę z nullistami od dłuższego czasu i sprawdzanie nulli też uważam za kiepski pomysł, o ile nie są one explicite dopuszczone.
Explicit null jest wtedy kiedy pole jest np. adnotowane jako @Nullable. Co i tak nadal jest słabe, bo najlepiej jak nulli nie ma w ogóle. A pola opcjonalne są po prostu opakowane w Option.
Nie da się wtedy tego przeoczyć.

Jakiś czas temu zaczęło mnie męczyć przedzieranie się przez tony null checków, żeby dojść do tej jednej / biednej linijki z logiką.
Z drugiej strony tutaj oczywiście odpornośc na null dość łatwo zrobić... tylko nie wiadomo czy warto. Szybie wywalenie się to też zaleta. Zamiast wstawiać te nulle z przodu, czy z tyłu i pchać problem do następnej warstwy....

0
yarel napisał(a):
  1. Jest taki interfejs: https://docs.oracle.com/javase/8/docs/api/java/lang/Comparable.html, który ma metodę compreTo, która powinna zwracać "a negative integer, zero, or a positive integer as this object is less than, equal to, or greater than the specified object.".
  2. Jest coś takiego jak https://pl.wikipedia.org/wiki/Porządek_leksykograficzny - sprawdź jak zadziała Twoje compareTo, jak zredukujesz implementację do prymitywnego return this.getEvnetDate().compareTo(o2.getEventDate()); (prymitywnego, bo wywali się na Eventach, które nie mają ustawionej daty).
  3. Dlaczego nie użyjesz po prostu API do sortowania tablic ?

No i dlaczego nie zrobiłem tak od razu ?? :D

   public static void sortEvent(Event[] events) {
        Arrays.sort(events, (x1,x2) -> x1.getEventDate().compareTo(x2.getEventDate()));
        System.out.println("Posortowane eventy: " + Arrays.toString(events));
    }

1 użytkowników online, w tym zalogowanych: 0, gości: 1