Laboratorium 9 - Województwa, powiaty, gminy - sortowanie i filtrowanie

Zapoznaj się z treścią wykładów dotyczących:

Sortujemy listę jednostek administracyjnych

Listy w Java mają funkcję sort(), której argumentem jest Comparator<T> referencja do klasy zapewniającej funkcję do porównywania elementów public int compare(T t, T t1).

Funkcja powinna zwrócić

  • wartość ujemną, jeżeli w wyniku sortowania 't' ma się znaleźć przed 't1'
  • 0, jeżeli elementy są równe
  • wartość dodatnią, jeżeli 't' ma się znaleźć po 't1'

Użyj lokalnej nazwanej klasy wewnętrznej

Napisz funkcję sortInplaceByName(). Wewnątrz zdefiniuj klasę dziedziczącą po Comparator<AdminUnit>. utwórz obiekt tej klasy i przekaż do funkcji sort()

    /**
     * Sortuje daną listę jednostek (in place = w miejscu) 
     * @return this
     */
    AdminUnitList sortInplaceByName(){
    ...
    }

Użyj lokalnej klasy anonimowej

Napisz funkcję używając w niej lokalnej klasy anonimowej (zdefiniowanej w locie jako new Comparator<AdminUnit>(){…}).

    /**
     * Sortuje daną listę jednostek (in place = w miejscu) 
     * @return this
     */
    AdminUnitList sortInplaceByArea(){
    ...
    }

Użyj wyrażenia lambda

Patrz Wyrażenia lambda i strumienie przykład na stronie 13

Napisz funkcję korzystając z wyrażenia lambda

    /**
     * Sortuje daną listę jednostek (in place = w miejscu) 
     * @return this
     */
    AdminUnitList sortInplaceByPopulation(){
    ...
    }

Piszemy bardziej ogólne funkcje

Zaimplementuj funkcje

    AdminUnitList sortInplace(Comparator<AdminUnit> cmp){
    //
    return this;
    }

oraz

  AdminUnitList sort(Comparator<AdminUnit> cmp){
  // Tworzy wyjściową listę
  // Kopiuje wszystkie jednostki
  // woła sortInPlace
    }

Filtrowanie

Użyjemy interfejsu Predicate a zwłaszcza jego metody test().

Napisz

  /**
     *
     * @param pred referencja do interfejsu Predicate
     * @return nową listę, na której pozostawiono tylko te jednostki, 
     * dla których metoda test() zwraca true
     */
    AdminUnitList filter(Predicate<AdminUnit> pred){

Poeksperymentuj z różnymi warunkami.

Np. kod, który wyświetla jednostki o nazwach na “Ż” posortowane według powierzchni może wyglądać następująco

list.filter(a->a.name.startsWith("Ż")).sortByArea().list(out);

Napisz:

  • wybór (i sortowanie) elementów zaczynających się na “K”
  • wybór jednostek będących powiatami, których parent.name to województwo małopolskie
  • zaproponuj kilka podobnych kryteriów selekcji

Interfejs Predicate<T> ma metody (standardowe implementacje metod) and or oraz negate. Zaproponuj kryteria selekcji używające tych funkcji Oczywiście za każdym razem możesz używać klas anonimowych w stylu

Predicate<AdminUnit> p = new Predicate(){ // i tu naciśnij Alt Enter

albo krótszych wyrażeń lambda.

Ograniczanie liczby wyjściowych elementów

Zaimplementuj filtrowanie z parametrem limit

    /**
     * Zwraca co najwyżej limit elementów spełniających pred 
     * @param pred - predykat
     * @param limit - maksymalna liczba elementów
     * @return nową listę
     */
    AdminUnitList filter(Predicate<AdminUnit> pred, int limit){
        throw new RuntimeException("Not implemented yet")
    }

Zaimplementuj również funkcję:

    /**
     * Zwraca co najwyżej limit elementów spełniających pred począwszy od offset
     * Offest jest obliczany po przefiltrowaniu
     * @param pred - predykat
     * @param - od którego elementu
     * @param limit - maksymalna liczba elementów
     * @return nową listę
     */
    AdminUnitList filter(Predicate<AdminUnit> pred, int offset, int limit){
        throw new RuntimeException("Not implemented yet")
    }

… czyli dla wywołania filter(pred,100,50) spośród 138 spełniających predykat pred wypisze te o indeksach 100-137. Ale nie bardzo chcemy zastosować rozwiązanie: utwórz nową listę za pomocą filter(pred) i wybierz z niej elementy…

AdminUnitQuery

Napisz stosunkowo prostą klasę AdminUnitQuery skupiającą specyfikację (i wykonanie) tych wszystkich operacji

public class AdminUnitQuery {
    AdminUnitList src;
    Predicate<AdminUnit> p = a->true;
    Comparator<AdminUnit> cmp;
    int limit = Integer.MAX_VALUE;
    int offset = 0;
 
    /**
     * Ustawia listę jako przetwarzane źródło
     * @param src
     * @return this
     */
    AdminUnitQuery selectFrom(AdminUnitList src){
    ...    
    }
 
    /**
     *
     * @param pred - ustawia predykat p
     * @return this
     */
    AdminUnitQuery where(Predicate<AdminUnit> pred){
    ...    
    }
 
    /**
     * Wykonuje operację p = p and pred
     * @param pred
     * @return this
     */
    AdminUnitQuery and(Predicate<AdminUnit> pred){
    ...    
    }
    /**
     * Wykonuje operację p = p or pred
     * @param pred
     * @return this
     */
    AdminUnitQuery or(Predicate<AdminUnit> pred){
    ...    
    }
 
    /**
     * Ustawia komparator cmp
     * @param cmp
     * @return this
     */
    AdminUnitQuery sort(Comparator<AdminUnit> cmp){
    ...    
    }
 
    /**
     * Ustawia limit
     * @param limit
     * @return this
     */
    AdminUnitQuery limit(int limit){
    ...    
    }
    /**
     * Ustawia offset
     * @param offset
     * @return this
     */
    AdminUnitQuery offset(int offset){
    ...    
    }
 
    /**
     * Wykonuje zapytanie i zwraca wynikową listę
     * @return przefiltrowana i opcjonalnie posortowana lista (uwzględniamy także offset/limit) 
     */
    AdminUnitList execute(){
    ...    
    }
}

Przetestuj uzupełniony kod w zapytaniach typu:

        AdminUnitQuery query = new AdminUnitQuery()
                .selectFrom(list)
                .where(a->a.area>1000)
                .or(a->a.name.startsWith("Sz"))
                .sort((a,b)->Double.compare(a.area,b.area))
                .limit(100);
        query.execute().list(out);

Napisz 3 własne propozycje zapytań

pz1/lab9.txt · Last modified: 2023/12/13 04:46 by pszwed
CC Attribution-Share Alike 4.0 International
Driven by DokuWiki Recent changes RSS feed Valid CSS Valid XHTML 1.0