Ordinare un TreeSet con il metodo "compareTo()"

di il
8 risposte

Ordinare un TreeSet con il metodo "compareTo()"

Salve a tutti!!! Ho un dubbio riguardo all'esercizio...l'ultimo metodo che dovrei implementare "public SortedSet<Student> sortBySurname()" mi chiede di ordinare un Set di Studenti in base al cognome! Quindi io creo una nuova collezzione di studenti di tipo TreeSet, poi mi viene chiesto di ordinare sti benedetti studenti in base al loro cognome con il metodo "compareTo()" ma non riesco a trovare un esempio chiaro da nessuna parte a riguardo e quindi non ho idea di come fare!!! Se qualcuno mi aiutasse con una bella spiegazione glie ne sarei molto molto molto grato!
/**
 * 
 */
package oop1314.lab05.exams.model;

import java.sql.Date;

import java.util.*;
import java.lang.Comparable;

import oop1314.lab05.exams.generics.AssociativeMemory;
import oop1314.lab05.exams.generics.IAssociativeMemory;

/**
 * @author
 * 
 */
public class Exam implements IExam, Comparable<Student>{

	private final Date date;
	private boolean isClosed = false;
	private final IAssociativeMemory<Student, Grade> map = new AssociativeMemory<>();
	/*
	 * TODO 1. Create a new field, a Set that will contain the students
	 */
	private Set<Student> students = new HashSet<>(); // OK
	/**
	 * @param examDate
	 *            the date for this exam
	 */
	
	public Exam(final Date examDate) { /* COSTRUTTOREEEEE */
		this.date = examDate;
	}

	
	@Override
	public void addStudent(final Student student) {
		if (!isClosed()) {
			
			students.add(student); // ok
			
		} else {
			System.out.println("This exam is closed, you cannot add students.");
		}
	}

	@Override
	public void assignGrade(final Student student, final Grade grade) {
		if (students.contains(student)){
		/*
		* TODO 3. If the student is included in the set OK
		*/
			map.put(student, grade);
		}
		else {
			System.out.println(student + " is not in this exam's list ");
		}
	}

	@Override
	public void close() {
		isClosed = true;
	}

	@Override
	public Date getDate() {
		return date;
	}

	@Override
	public Grade getGrade(final Student stud) {
		if (this.isClosed() && students.contains(stud)){
				/*
				 * TODO 4. and if the student is in the exam's list  OK!
				 */
				return map.get(stud);
		}
		System.out.println("This exam is not closed yet, or the student is not in list.");
		return null ;
	}

	@SuppressWarnings("null")
	@Override
	public Collection<Student> getStudents() {
		/*
		 * TODO 5. Return a COPY of the internal Set.
		 * 
		 * It is often better to CLONE the internal representation of the
		 * object, if you want to prevent outer classes from messing up your
		 * internal representation.
		 */
		
		TreeSet<Student> copyStudents = null ;
		copyStudents.addAll(students);
		
		return copyStudents ;
	}

	@Override
	public boolean isClosed() {
		return isClosed;
	}
	@Override
	public SortedSet<Student> sortBySurname() {
		
		TreeSet<Student> sortStudents = null ;
		sortStudents.addAll(students);
		
		
		return sortStudents ;
		
	}


	@Override
	public int compareTo(Student student) {
		// TODO Auto-generated method stub
		return null ;
	}	
		
		/*
		 * TODO 6. Use a TreeSet to sort the students.
		 * 
		 * You do not need to manually write a sort method: according to the
		 * Javadoc for ThreeSet (check it out!), this data structure
		 * automatically sorts elements when they're added. In order to do so,
		 * the elements must implement Comparable<T>, which specifies a int
		 * compareTo(T) method, which is used to determine an ordering between
		 * the current object and the one passed. In fact, you will implement
		 * Comparable in the next exercise, and everything will work smoothly.
		 */
}

8 Risposte

  • Re: Ordinare un TreeSet con il metodo "compareTo()"

    SsaLaroLana ha scritto:


    Salve a tutti!!! Ho un dubbio riguardo all'esercizio...l'ultimo metodo che dovrei implementare "public SortedSet<Student> sortBySurname()" mi chiede di ordinare un Set di Studenti in base al cognome! Quindi io creo una nuova collezzione di studenti di tipo TreeSet, poi mi viene chiesto di ordinare sti benedetti studenti in base al loro cognome con il metodo "compareTo()" ma non riesco a trovare un esempio chiaro da nessuna parte a riguardo e quindi non ho idea di come fare!!! Se qualcuno mi aiutasse con una bella spiegazione glie ne sarei molto molto molto grato!
    TreeSet è una collezione "sorted" e di conseguenza "ordered" (sorted vuol dire che è mantenuta ordinata in base al contenuto degli oggetti e ordered vuol dire che l'ordine di iterazione è prevedibile, insomma non è "a casaccio". Se una collezione è sorted, è di norma anche ordered).

    Come ho detto, TreeSet è "sorted", quindi è il contenuto degli oggetti a definire l'ordine interno nella collezione.
    L'ordine però si può basare o sul natural ordering cioè su Comparable oppure su un Comparator specifico (solo se si usa il costrutture TreeSet(Comparator<? super E> comparator) ).

    Se tu dici che ti è stato richiesto di usare espressamente compareTo(), allora si sta parlando di Comparable e questo di conseguenza vuol dire una sola cosa: che Student deve implementare Comparable e definire il compareTo() per confrontare sul cognome.

    Se è questo che devi fare ok, ricorda però che il natural ordering è uno solo, perché Comparable va implementato nella classe degli oggetti da comparare e quindi si può fare una volta sola. Di Comparator (sempre per quella classe di oggetti) invece ne puoi implementare quanti ne vuoi, perché va fatto in classi separate, cioè distinte da quella dei tuoi oggetti.


    P.S. E Exam che implementa Comparable<Student> non ha molto senso ....
  • Re: Ordinare un TreeSet con il metodo "compareTo()"

    "Si implementi Comparable<IPerson> in IPerson.
    Si implementi in AbstractPerson il metodo necessario a supportare
    Comparable<IPerson>. Tale metodo deve ordinare le persone
    alfabeticamente per cognome.
    Si ricorda che la classe String implementa gia
    Comparable<String>: le stringhe hanno ordine naturale uguale
    all'ordine alfabetico. "

    Questo è cio che mi viene chiesto dal testo dell'esercizio!!! Quindi implemento la classe "Comparable<>" nell'interfaccia IPersone, e poi ne definisco il metodo "compareTo()" nella relativa classe astratta "AbstractPerson". La domanda è, COME devo implementarlo questo metodo "compareTo()" per far si che abbia un TreeSet ordinato dalla A alla Z per cognome? Questo non riesco a capire...Grazie mille comunque per la risposta!! Sei stavo veramente molto chiaro,e grazi per il P.S. , lo sò che non ci sta a fare niente li,era una prova che avevo fatto e me lo son dimenticato li!
  • Re: Ordinare un TreeSet con il metodo "compareTo()"

    SsaLaroLana ha scritto:


    Quindi implemento la classe "Comparable<>" nell'interfaccia IPersone
    Nella interfaccia IPerson puoi solo dichiarare che estende Comparable<IPerson> (le interfacce non "implementano" qualcosa .... possono solo estendere altre interfacce).
    Se vuoi puoi dichiarare in IPerson il metodo compareTo ma non è obbligatorio, essendo una interfaccia un tipo implicitamente abstract.
    L'importante è che poi in una classe che implementa IPerson vai veramente ad implementare concretamente il compareTo.

    SsaLaroLana ha scritto:


    La domanda è, COME devo implementarlo questo metodo "compareTo()" per far si che abbia un TreeSet ordinato dalla A alla Z per cognome?
    Nel compareTo hai 2 oggetti, il this, l'oggetto su cui compareTo viene invocato (da TreeSet nel tuo caso) e l'altro oggetto che compareTo ha come parametro (chiamiamolo 'altro').
    Nel compareTo devi solo comparare il cognome del this con il cognome del 'altro'.
    E il suggerimento del testo "Si ricorda che la classe String implementa gia
    Comparable<String>
    " ti è utile, perché String ha un compareTo.
  • Re: Ordinare un TreeSet con il metodo "compareTo()"

    Dio...ma perchè non vieni a fare il prof da me? Sei velocissimo nelle risposte...e molto chiaro! Comnque si certo lo so che nelle interfaccia posso solo dichiarare il metodo ma ovviamente non posso implementarlo ma dovrò andare a realizzarlo nella classe che implementa l'interfaccia!Infatti AbstractPerson implementa tale interfaccia e quindi è li che andrò a creare il metodo! Grazie mille per la risposta!ma visto che il metodo "compareTo()" compara DUE elementi,come posso far si che mi ordini TUTTO il TreeSet in un comando solo? Non di certo con un ciclo visto che in teoria in una riga di comando posso svolgerlo quel punto dell'esercizio...
    	public int compareTo(Student student){
    		
    		return this.getSurname().compareTo(student.getSurname());
    	}
    Questo è ciò che mi viene in mente...ma ancora non capisco come possa ordinare qualcosa...certo mi restituisce un valore in base all'ordinamento nell'alfabeto...pero restituisce un valore e basta...non va a fare ordinamento in base al cognome...mi dice solo se il cognome dello studente this. è minore,uguale o maggiore allo Studente "student" e fine...
  • Re: Ordinare un TreeSet con il metodo "compareTo()"

    SsaLaroLana ha scritto:


    Dio...ma perchè non vieni a fare il prof da me? Sei velocissimo nelle risposte...e molto chiaro!
    Ti ringrazio per l'apprezzamento, ma non ho mai avuto velleità di fare il "prof" (non potrei neanche ...).

    SsaLaroLana ha scritto:


    ma visto che il metodo "compareTo()" compara DUE elementi,come posso far si che mi ordini TUTTO il TreeSet in un comando solo? Non di certo con un ciclo visto che in teoria in una riga di comando posso svolgerlo quel punto dell'esercizio...
    No il tuo ragionamento qui è sbagliato. compareTo non deve "pensare" sull'insieme ma solo su una coppia di valori. Il perché è facile da spiegare e capire.
    La comparazione degli oggetti si applica a TreeSet ma anche ad esempio alle liste (List), che sono ordinabili con il metodo sort di Collections.
    In entrambi i casi è l'algoritmo di ordinamento interno a TreeSet o sort che si occupa di fare un certo numero di "combinazioni" di coppie di valori da confrontare con compareTo (di Comparable) o compare (di Comparator) in modo da dedurre l'ordine complessivo e ottenere poi alla fine un insieme ordinato.

    Collections.sort farà molte combinazioni e quindi molti confronti su coppie di valori, proporzionalmente alla lunghezza della lista. TreeSet è basato su un tipo di "albero" binario detto "red-black" (ogni nodo ha max 2 figli). In TreeSet però l'albero è già mantenuto ordinato, quindi quando aggiungi 1 elemento, TreeSet ha bisogno di fare solo poche comparazioni, scendendo nell'albero, per trovare il nodo in cui inserire l'elemento.

    SsaLaroLana ha scritto:


    	public int compareTo(Student student){
    		
    		return this.getSurname().compareTo(student.getSurname());
    	}
    Perfetto.

    Solo una piccola annotazione: presuppone però che surname non sia null. Se può essere null, dovresti valutare come fare la comparazione, cioè tra un null e un cognome, null viene prima o dopo? (puoi sceglierlo tu)
  • Re: Ordinare un TreeSet con il metodo "compareTo()"

    Bè io sceglierei di far venire il "null" dopo...Comunque sia grazie mille...quel problema è stato risolto...(il 90% è merito tuo )...ora vorrei chiederti ( ti sfrutto un pò ), in questa classe mi viene chiesto di implementare due liste generiche una di tipo K e l'altra di tipo V...non capisco però il costruttore come va implementato...io ho fatto cosi ma ho l'impressione che qualcosa sia sbagliato...
    public class AssociativeMemory<K, V> implements IAssociativeMemory<K, V> {
    	
    	private List<K> first ;
    	private List<V> second ;
    	private int index ;
    	
    	/*
    	 * TODO 1. Create two Lists. One will must contain elements of type "K", the
    	 * other elements of type "V". Use generics properly.
    	 */
    
    	@Override
    	public void put(final K key, final V value) {
    		
    		this.first.add(index, key);
    		this.second.add(index,value);
    		this.index++ ;
    		/*
    		 * TODO 2. Add the key and value to the respective lists, in the same
    		 * position.
    		 */
    	}
  • Re: Ordinare un TreeSet con il metodo "compareTo()"

    SsaLaroLana ha scritto:


    in questa classe mi viene chiesto di implementare due liste generiche una di tipo K e l'altra di tipo V...non capisco però il costruttore come va implementato...io ho fatto cosi ma ho l'impressione che qualcosa sia sbagliato...
    Già dal nome "AssociativeMemory<K, V>" a me fa pensare ad una collezione di "associazioni" tra chiavi e valori. Generalmente si fa con una "map" ma se a te è stato chiesto di usare 2 liste .... beh, ok, non sto a discutere.

    Il punto è solo decidere quale implementazione concreta di lista usare (List è solo l'interfaccia). Ci sono principalmente ArrayList, LinkedList e il "vecchio" Vector (più altre più specifiche).

    Nella tua classe è bene che ci sia un costruttore, dovrà semplicemente istanziare le due liste (usando sempre <K> e <V> per la parametrizzazione) e assegnarle ai campi.

    Non mi è chiaro perché vuoi usare quel 'index'. Le liste sono espandibili già di per sé, basta fare add(valore). Se usi l'altro add(indice, valore) in genere è per inserire non al fondo ma in mezzo (o all'inizio).
  • Re: Ordinare un TreeSet con il metodo "compareTo()"

    Ah ecco...sai venendo da programmazione in C ero abituato a dovermele espandere le liste... quindi si "index" non serve assolutamente a niente...e si mi viene esplicitamente richiesto l'uso di due liste appunto quindi seguo le loro richieste...Giustamente io sono un patacca perchè uso un'interfaccia...guardando uno schema UML ho infatti visto i tre tipi di liste che implementano List...in particolare come hai detto tu ArrayList e LinkedList...proveddero con ArrayList che mi sembra piu adatto a una cosa semplice ( per chi lo sà fare ) come questa!...
Devi accedere o registrarti per scrivere nel forum
8 risposte