Pagina 1 di 2 1 2 ultimoultimo
Visualizzazione dei risultati da 1 a 10 su 12
  1. #1
    Utente di HTML.it
    Registrato dal
    Oct 2014
    residenza
    Padova
    Messaggi
    361

    Gestione ordinamento di una tabella di dati

    Salve a tutti, ho un paio di domande che mi ronzano in testa, spero possiate aiutarmi


    In una parte dell'applicazione che sto sviluppando l'utente può vedere in una JTable tutte le partite salvate in una determinata cartella.
    Alla classe che crea e mostra la tabella viene passato come parametro un ArrayList<Game>.
    La classe Game ovviamente rappresenta una singola partita,sotto posto il codice.


    Adesso vorrei implementare la possibilità di ordinare la tabella in base a ciascuna colonna, in ordine crescente e decrescente.
    Vorrei quindi qualche consiglio su come gestire l'ordinamento.
    In primo luogo, visto che sto memorizzando le partite in un ArrayList, avevo intenzione di utilizzare Collections.sort() per ordinare le partite.
    Game dovrebbe quindi estendere Comparable<Game> e aver definito il metodo compareTo(Game g).
    All'interno del compareTo deve essere conoscibile la colonna su cui voglio eseguire l'ordinamento e se l'ordinamento sia crescente o decrescente.


    Avevo quindi intenzione di memorizzare queste due informazioni con due variabili statiche e scrivere il tutto in questo modo:


    codice:
    import java.util.ArrayList;
    public class Game implements Comparable<Game>
    {
    	boolean seen;
    	ArrayList<String> moves;
    	String white="",black="",whiteRank="",blackRank="",type="",result="",date="",comment="",path="";
    	static boolean ascending=true;
    	static int sort=0;
    	
    	//.... altri metodi
    	
    	public int compareTo(Game g)
    	{
    		if(sort==0&&ascending)return path.compareTo(g.path);
    		else if(sort==0)return g.path.compareTo(path);
    		else if(sort==1&&ascending)return date.compareTo(g.date);
    		else if(sort==1)return g.date.compareTo(date);
    		else if(sort==2&&ascending)return white.compareTo(g.white);
    		else if(sort==2)return g.white.compareTo(white);
    		else if(sort==3&&ascending)return black.compareTo(g.black);
    		else if(sort==3)return g.black.compareTo(black);
    		else if(sort==4&&ascending)return whiteRank.compareTo(g.whiteRank);
    		else if(sort==4)return g.whiteRank.compareTo(whiteRank);
    		else if(sort==5&&ascending)return blackRank.compareTo(g.blackRank);
    		else if(sort==5)return g.blackRank.compareTo(blackRank);
    		else if(sort==6&&ascending)return type.compareTo(g.type);
    		else if(sort==6)return g.type.compareTo(type);
    		else if(sort==7&&ascending)return comment.compareTo(g.comment);
    		else return g.comment.compareTo(comment);
    	}
    }

    Può andare bene il metodo di ordinamento? Il tutto è molto corposo ma del resto voglio fornire molti tipi di ordinamento...
    Accetto volentieri consigli su questa parte, anche su come memorizzare la colonna e il tipo di ordinamento, che al momento pensavo di impostare dall'esterno,modificando le variabili statiche sort e ascending.


    La seconda cosa che volevo chiedere è questa: durante il caricamento delle partite, in un thread separato, aggiorno una JProgressBar in base al numero di file letti e numero di file totali.
    Volevo fare una cosa simile durante l'ordinamento delle partite, c'è un modo carino per sapere quanto durerà il processo o sono costretto a usare la modalità indeterminata della barra?

    Grazie dell'aiuto

  2. #2
    Utente di HTML.it L'avatar di andbin
    Registrato dal
    Jan 2006
    residenza
    Italy
    Messaggi
    18,284
    Quote Originariamente inviata da Ansharja Visualizza il messaggio
    Può andare bene il metodo di ordinamento?
    No, non va affatto bene. Innanzitutto è lungo, sicuramente meno performante e il fatto di avere un int sort messo come static è un pessimo design. Ed esiste anche un'altra questione concettuale: Comparable, essendo implementabile una volta sola per una certa classe di oggetti, dovrebbe rappresentare il criterio di ordinamento "naturale" per quella classe di oggetti (es. per una classe Persona, l'ordinamento più naturale è per cognome poi per nome).
    Il tuo invece risulterebbe un miscuglio ...

    Dovresti implementare Comparator in classi separate. Per il ascending/descending, non è per forza necessario implementare entrambi. Collections ha un metodo per invertire un Comparator.

    Quote Originariamente inviata da Ansharja Visualizza il messaggio
    Volevo fare una cosa simile durante l'ordinamento delle partite, c'è un modo carino per sapere quanto durerà il processo o sono costretto a usare la modalità indeterminata della barra?
    Quanti elementi pensi di ordinare? 50, 500, 5000? Se sei su questi numeri, l'ordinamento è quasi istantaneo. Fai qualche benchmark.
    Andrea, andbin.devSenior Java developerSCJP 5 (91%) • SCWCD 5 (94%)
    java.util.function Interfaces Cheat SheetJava Versions Cheat Sheet

  3. #3
    Utente di HTML.it
    Registrato dal
    Oct 2014
    residenza
    Padova
    Messaggi
    361
    Grazie della risposta intanto andbin

    Quel terribile miscuglio dava fastidio anche a me, ma per pigrizia non avevo pensato a fare diversi Comparator.

    Però hai ragione, anche il design è del tutto sbagliato, domani penso a come sistemare il tutto.

    Per quanto riguarda il numero di elementi sono sulle diverse migliaia, ma effettivamente ho notato che l'ordinamento è quasi istantaneo,come hai detto.

    Ora però mi viene comunque la curiosità di sapere se era fattibile a livello teorico pensare di aggiornare la barra in modo preciso, se hai qualche idea idea sono tutto orecchi

  4. #4
    Utente di HTML.it L'avatar di andbin
    Registrato dal
    Jan 2006
    residenza
    Italy
    Messaggi
    18,284
    Quote Originariamente inviata da Ansharja Visualizza il messaggio
    Ora però mi viene comunque la curiosità di sapere se era fattibile a livello teorico pensare di aggiornare la barra in modo preciso, se hai qualche idea idea sono tutto orecchi
    Ci sono due questioni. Innanzitutto quella fondamentale. Se durante un sort vuoi far mostrare/aggiornare qualcosa, allora il sort deve essere eseguito in un thread che non sia il Event Dispatch Thread. Con tutto quello che ovviamente comporta in termini di multi-threading, sincronizzazione, ecc...
    In una applicazione Swing, se fai un sort (o qualunque altra operazione "lunga") nel contesto del EDT (es. a seguito di un evento), stai tenendo tu impegnato il EDT e quindi nulla può essere aggiornato visivamente.

    La seconda questione è che se usi Collections.sort() sai solo quando inizia e quando finisce (cioè fai tu qualcosa appena prima e appena dopo). Non hai nessun'altra informazione. Non c'è alcuna API o callback che permetta di sapere cosa sta facendo, a che punto è, quanto tempo anche stimato gli rimane, ecc... Insomma, non c'è alcun appiglio su questi aspetti.
    Se implementassi tu un algoritmo di ordinamento, chiaramente uno di quelli noti (difficilmente se ne "inventano" di nuovi), e magari lo rendi generalizzato in funzione di Comparable/Comparator, allora avresti più controllo. Potresti offrire una API apposita per fornire informazioni sull'avanzamento e cose del genere.
    Andrea, andbin.devSenior Java developerSCJP 5 (91%) • SCWCD 5 (94%)
    java.util.function Interfaces Cheat SheetJava Versions Cheat Sheet

  5. #5
    Utente di HTML.it
    Registrato dal
    Oct 2014
    residenza
    Padova
    Messaggi
    361
    Bene grazie, terrò a mente queste indicazioni.

    Se trovo problemi nel risistemare l'ordinamento torno a rompere qui

  6. #6
    Utente di HTML.it
    Registrato dal
    Oct 2014
    residenza
    Padova
    Messaggi
    361
    Allora per adesso ho risistemato il codice in questo modo:

    codice:
    import java.util.ArrayList;
    import java.util.Collections;
    import java.util.Comparator;
    public class TableSort
    {
        boolean descending;
        int sort;
        Comparator<Game> comparator;
        public TableSort(int s,boolean d)
        {
            sort=s;
            descending=d;
        }
        public void sort(ArrayList<Game> games)
        {
            if(sort==0)comparator=new PathComparator();
            else if(sort==1)comparator=new DateComparator();
            else if(sort==2)comparator=new WhiteComparator();
            else if(sort==3)comparator=new BlackComparator();
            else if(sort==4)comparator=new WhiteRankComparator();
            else if(sort==5)comparator=new BlackRankComparator();
            else if(sort==6)comparator=new TypeComparator();
            else if(sort==7)comparator=new CommentComparator();
            else return;
            if(descending)comparator=Collections.reverseOrder(comparator);
            Collections.sort(games,comparator);
        }
        class PathComparator implements Comparator<Game>
        {
            public int compare(Game g,Game h){
                return g.path.compareTo(h.path);
            }
        }
        class DateComparator implements Comparator<Game>
        {
            public int compare(Game g,Game h){
                return g.date.compareTo(h.date);
            }
        }
        class WhiteComparator implements Comparator<Game>
        {
            public int compare(Game g,Game h){
                return g.white.compareTo(h.white);
            }
        }
        // ... stessa storia per gli altri comparatori
    }
    Va bene come design ?

  7. #7
    Ti posso suggerire una struttura di Switch-case invece di tutti quegli if - else if.
    Ciao.
    I computer sono incredibilmente veloci, accurati e stupidi.
    Gli uomini sono incredibilmente lenti, inaccurati e intelligenti.
    Insieme sono una potenza che supera l'immaginazione.

    A.Einstein

  8. #8
    Utente di HTML.it L'avatar di andbin
    Registrato dal
    Jan 2006
    residenza
    Italy
    Messaggi
    18,284
    Quote Originariamente inviata da Ansharja Visualizza il messaggio
    Allora per adesso ho risistemato il codice in questo modo
    Ok, già meglio di prima sicuramente, non ci sono campi static.
    La classe però è molto migliorabile e per diversi aspetti.

    - Ti è già stato suggerito sopra l'uso di un switch, questo aiuta sicuramente a rendere più pulito (ma anche più efficiente) il codice.
    - Se usassi delle costanti letterali sarebbe ancora meglio e più leggibile, specialmente nel/nei punto/i dove istanzi i TableSort. Invece che 6 es. TYPE_ORDER. Se le facessi come enum (che con lo switch sono ottime) sarebbe ancora meglio.
    - Come suggerimento, abituati a tenere le variabili di istanza generalmente come "private", salvo casi (e certi design) davvero particolari. Quelle di TableSort non sono private. E non lo sono nemmeno quelle in Game, visto che fai g.white, g.date ecc.... Puoi accedere ai campi anche dalle classi dei comparator, perché quelle variabili sono sicuramente non private. Con le variabili di istanza private, devi definire degli appositi metodi getter/setter.
    - Le classi dei comparatori tecnicamente le hai fatte come "regular" inner-class. Una inner-class ha una relazione molto particolare con la classe che la contiene. Nel tuo caso questo non serve. Puoi farle come classi top-level a sé stanti. Oppure tenerle dentro TableSort ma farle come "nested" (static) class che sono semplicemente marcate static.
    - Non mi piace tantissimo il fatto che la scelta del comparator la fai nel tuo metodo sort ma non ho capito se volevi fare la classe TableSort per avere sue istanze mutabili o immutabili. Questo farebbe la differenza. Se fosse immutabile, la scelta del comparator la farei nel costruttore.
    Andrea, andbin.devSenior Java developerSCJP 5 (91%) • SCWCD 5 (94%)
    java.util.function Interfaces Cheat SheetJava Versions Cheat Sheet

  9. #9
    Utente di HTML.it
    Registrato dal
    Oct 2014
    residenza
    Padova
    Messaggi
    361
    Quote Originariamente inviata da schumy2000 Visualizza il messaggio
    Ti posso suggerire una struttura di Switch-case invece di tutti quegli if - else if.
    Ciao.
    Ma dici a livello prestazionale?
    Come codice preferisco usare di molto l'else if

    [EDIT] Visto il doppio suggerimento, questa parte dopo la cambio

    @anbin: non avevo visto che avevi scritto anche tu, ora leggo tutto
    Ultima modifica di Ansharja; 12-01-2016 a 22:03

  10. #10
    Utente di HTML.it
    Registrato dal
    Oct 2014
    residenza
    Padova
    Messaggi
    361
    Grazie ancora per la pazienza!

    Quote Originariamente inviata da andbin Visualizza il messaggio
    - Ti è già stato suggerito sopra l'uso di un switch, questo aiuta sicuramente a rendere più pulito (ma anche più efficiente) il codice.
    - Se usassi delle costanti letterali sarebbe ancora meglio e più leggibile, specialmente nel/nei punto/i dove istanzi i TableSort. Invece che 6 es. TYPE_ORDER. Se le facessi come enum (che con lo switch sono ottime) sarebbe ancora meglio.
    Alle costanti letterali avevo in realtà già pensato, visto che con Swing ne faccio molto uso, modificherò a breve la cosa.
    Confesso invece la mia ignoranza su enum e switch: a me sembrava terribile il dover ripetere la clausola break per uscire dai vari case, ma se dite che è più performante implemento quella soluzione.
    Le enum non le ho proprio mai usate invece, altra cosa da guardarmi

    Quote Originariamente inviata da andbin Visualizza il messaggio
    - Come suggerimento, abituati a tenere le variabili di istanza generalmente come "private", salvo casi (e certi design) davvero particolari. Quelle di TableSort non sono private. E non lo sono nemmeno quelle in Game, visto che fai g.white, g.date ecc.... Puoi accedere ai campi anche dalle classi dei comparator, perché quelle variabili sono sicuramente non private. Con le variabili di istanza private, devi definire degli appositi metodi getter/setter.
    Per quanto riguarda la definizione dei campi come private e l'uso dei metodi getter/setter, ho già letto (anche su altri forum) i vantaggi di questo approccio, dovrei essere meno testardo ed adeguarmi.

    Quote Originariamente inviata da andbin Visualizza il messaggio
    - Le classi dei comparatori tecnicamente le hai fatte come "regular" inner-class. Una inner-class ha una relazione molto particolare con la classe che la contiene. Nel tuo caso questo non serve. Puoi farle come classi top-level a sé stanti. Oppure tenerle dentro TableSort ma farle come "nested" (static) class che sono semplicemente marcate static.
    Ricevuto, volevo solo evitare la sovrabbondanza di file, se i due approcci sono equiparabili le segnerò come static

    Quote Originariamente inviata da andbin Visualizza il messaggio
    - Non mi piace tantissimo il fatto che la scelta del comparator la fai nel tuo metodo sort ma non ho capito se volevi fare la classe TableSort per avere sue istanze mutabili o immutabili. Questo farebbe la differenza. Se fosse immutabile, la scelta del comparator la farei nel costruttore.
    Non mi è chiarissimo questo punto, TableSort la utilizzerei solo per l'ordinamento...
    Dici di inserire solo la scelta del Comparator nel costruttore o inglobarci anche il resto del metodo sort() ?

    Penso la prima comunque, mi ricordo di aver letto un tuo consiglio sul fatto di non demandare troppa logica a un costruttore.
    Se ho capito bene, sistemo il tutto.

    Grazie ancora

Permessi di invio

  • Non puoi inserire discussioni
  • Non puoi inserire repliche
  • Non puoi inserire allegati
  • Non puoi modificare i tuoi messaggi
  •  
Powered by vBulletin® Version 4.2.1
Copyright © 2025 vBulletin Solutions, Inc. All rights reserved.