Mechanizmy sortowania - trudności z implementacją komparatorów

0

Cześć!
Sprawa polega na tym, że na studiach mamy teraz zadania związane z analizą wydajności różnych algorytmów sortowania. Na pierwszy ogień poszły bąbelkowe, przez wybieranie i przez wstawianie. Mamy napisać klasy dla odpowiedniego typu sortowania, potem w konstruktorze połączyć je z danym komparatorem (np. jeden komparator porównuje studentów po ocenie, a drugi po indeksie) i wg klucza komparatora posortować daną np. ArrayListę 500000 elementów. No i mam problem głównie z mainem, czyli programem testowym, bo nie wiem, jak to ze sobą połączyć, żeby grało.
Mam parę klas, które zaraz wkleję. Są to BubbleSort definiujący algorytm sortowania bąbelkowego, prosty interfejs Comparator, klasę student implementującą ten interfejs i mającą metodę Compare.

import java.util.ArrayList;
public class BubbleSort {
   
        private final Comparator comparator;
   
        public BubbleSort(Comparator comparator) {
                this.comparator = comparator;
        }
  
        public ArrayList<Student> sort(ArrayList<Student> list) {
                int size = list.size();
                for (int pass = 1; pass < size; ++pass) {
                        for (int left = 0; left < (size - pass); ++left) {
                                int right = left + 1;
                                if (comparator.compare(list.get(left), list.get(right)) > 0)
                                        swap(list, left, right);
                        }
                }
                return list;
        }
   
        public int compare(Object left, Object right) throws ClassCastException
                        { return comparator.compare(left, right); }
 
   
        private void swap(ArrayList list, int left, int right) {
                Object temp = list.get(left);
                list.set(left, list.get(right));
                list.set(right, temp);
        }
}
 
 public class Student implements Comparator<Student> {
   
        int ocena;
        int indeks;
   
        public Student(int ocena, int index) {
                this.ocena = ocena;
                indeks = index;
        }
   
        public String toString() {
                return "Numer indeksu: " + indeks + " ocena: " + ocena + "\n";
        }
   
        public int getIndeks() {
                return indeks;
        }
   
        public int getOcena() {
                return ocena;
        }
   
        public int compare(Student left, Student right) {
                if (left.getIndeks()<right.getIndeks()) {
                        return -1;
                }
                if (left.getIndeks() == right.getIndeks()) {
                        return 0;
                }
                else {
                        return 1;
                }
        }
   
}
public interface Comparator<T> {
        public int compare(T left, T right) throws ClassCastException;
} 
import java.util.Random;
import java.util.ArrayList;
public class Program {
        public static void main(String[] args) {
                int elementy = 500000;
                ArrayList<Student> lista = new ArrayList<Student>();
                Random rand = new Random();
                for (int i=0; i<elementy; i++) {
                        lista.add(new Student(rand.nextInt(4)+2, rand.nextInt(900000)));
                }
                System.out.println(lista);
        }
   
} 

W mainie, jak widać, mam ledwo stworzoną losową ArrayListę ze studentami. Nie wiem, jak zarzucić tam BubbleSorta, żeby to się posortowało. Mamy to zrobić właśnie wg takiej filozofii. Klasy inny sortowań z algorytmami oczywiście sobie sam dorzucę, a implementacja będzie identyczna jak przy BubbleSort...tylko, że nie wiem, jak to BS zaimplementować w tym mainie :)
No i druga sprawa...czy to Compare w Studencie to dobre podejście? :/ Zdaje się, że powinienem to zrobić chyba inaczej, bo teraz jeśli będę chciał posortować po ocenie zamiast po indeksie, będę musiał zmienić metodę compare :/

0

Zwróć uwagę jak jest to rozwiązane w klasie Collections. Statyczna metoda sortująca, która jako parametr przyjmuje listę obiektów do posortowania i komparator. Stwórz jedną klasę ze statycznymi metodami sortującymi. Dodatkowo, stwórz klasę student z wewnętrznymi klasami, które będą twoimi komparatorami, jeden sortujący po indeksie drugi po ocenie. W metodzie main() tworzysz listę obiektów klasy Student następnie wywołujesz metodę sortującą i po kłopocie.

0

Student powinien implementować Comparable, nie Comparator.

0

Jeżeli Student będzie implementował Comparable to będzie miał tylko jedną metodę compare(), nie będzie się dało w prosty sposób porównywać dwóch studentów po indeksie lub po ocenie. Jeżeli jednak oprócz klasy Student stworzymy (na przykład jako klasę wewnętrzną) swoje własne Comparatory (implementujące interfejs Comparator) to do metody sortującej możemy podać dowolny z nich i w zależności od potrzeb sortować po dowolnym polu. A jeszcze lepiej napisać uniwersalny Comparator, który porównuje dowolne dwa obiekty po dowolnym polu. Np:


import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.Comparator;

public class UComparator<T> implements Comparator<T> {

	private Method m;
	// Konstruktor wywoływany z argumentami nazwa klasy i pola, po którym 
	// chcemy posortować, przypisuje zmiennej m metodę zwracającą pole
	// field (getField)
	public UComparator(Class c,String field) throws NoSuchMethodException, SecurityException, ClassNotFoundException {
		m = Class.forName(className).getMethod("get"+ field.substring(0, 1).toUpperCase() + field.substring(1));		
	}	
	
	//Zakładając, że pole field jest Comparable wywołujemy metodę m na obiektach
	// arg0 i arg1 a otrzymane wartości porównujemy metodą compareTo()
	@SuppressWarnings("unchecked")
	@Override
	public int compare(T arg0, T arg1) {
		int wynik = 0;
		try {
			wynik = ((Comparable<T>) m.invoke(arg0)).compareTo((T) m.invoke(arg1));
			
		} catch (IllegalAccessException | IllegalArgumentException
				| InvocationTargetException e) {
			e.printStackTrace();
		}		
		return wynik;
	}

} 
0

Refleksja jest prawie zawsze zlym pomyslem, a w tym wypadku jestem tego na bank pewien.
Moim zdaniem najlepszym pomyslem bedzie uzycie lambda z jdk8 jak masz taka mozliwosc ;d

0

Student ma być prostą klasą, a Comparatory mają być osobno i najlepiej na zewnątrz. Comparatory mogą być bezproblemowo singletonami bo nie posiadają stanu.

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