2009-12-06 14 views
7

Java: come si eseguono operazioni di elenco con definizioni diverse di uguali?Java: come si eseguono operazioni di elenco con diverse definizioni di uguali?

Ho due elenchi di POJO generici. Devo eseguire alcune operazioni sugli elenchi in base a diversi modi di confrontare i POJO all'interno degli elenchi.

Per esempio, se il mio POJO aveva la seguente struttura:

public class GenericPojo { 
    private String id; 
    private String address; 
    private String city; 
    private String country; 
    private String extraDetails; 
} 

(con i getter appropriati e setter)

dato List1<GenericPojo> e List2<GenericPojo>, come avrei trovato:

List1 - List2 (dove le classi GenericPojo sono uguali se solo gli ID sono uguali)

Intersect of Lis t1 e List2 (dove id, address, city, country, ma non extraDetails di GenericPojo sono uguali)

Would due diverse classi di confronto personalizzate essere utile qui? Ci sono librerie che gestiscono queste operazioni in modo efficace o dovrei provare a implementare la mia?

+0

Questa è la mia prima domanda, se ho commesso errori di stile o altri errori, per favore modifica e fammi sapere cosa ho sbagliato. –

+0

Nota è possibile ottenere il testo da formattare come codice indentandolo in almeno quattro spazi. Puoi anche utilizzare il pulsante codice ("101 \ n010") nella barra dell'editor per indentare. – outis

+0

Quando si ottiene l'intersezione, si desidera creare due elenchi, quindi entrambi gli extraDetails sono rappresentati oppure uno dei due è sufficiente? – Buhb

risposta

2

Se è necessario manipolare la classe fuori dal proprio controllo, suggerirei di utilizzare la delega. Ecco la mia prova:

  1. Creare un RichList<T> wrapper List s di attuazione del contratto List, sulla base del decorator pattern.
  2. Creare un inteface EqualityChecker<T>, con un unico metodo `public boolean uguale (T t1, T, t2).
  3. Implementare questa interfaccia per il tuo pojo generico due volte: una controlla solo l'ID e l'altra controlla gli altri campi.
  4. Aggiungi entrambi i metodi a cui sei interessato (imposta la sottrazione e imposta l'intersezione), ma con un argomento supplementare che è l'istanza concreta EqualityChecker<T> che eseguirà il test di uguaglianza per te.

modo da poter aggiungere entrambe le operazioni per tutte le esistenti List s per ogni tipo di oggetto per cui si è scritto un EqualityChecker.

Ulteriori miglioramenti: È anche possibile scrivere un predefinitaEqualityChecker<T> che chiama semplicemente il metodo equals degli oggetti confrontati. È quindi possibile sovraccaricare entrambe le nuove operazioni per impostare l'impostazione predefinita su EqualityChecker.

1

Se le liste non contengono duplicati (con l'analisi delle classi di confronto personalizzate ipotetiche) è possibile utilizzare due TreeSet, rispettivamente, istanziati con i due comparatori rispettivamente.

Uno svantaggio di questo (a parte il vincolo di duplicazione) è che l'ordine che si ottiene quando si itera su elementi dipende dai comparatori.

1

Dato i requisiti specifici per l'uguaglianza, List#removeAll() e List#retainAll() non si adatta alle vostre esigenze quindi penso che avrete bisogno di un'implementazione personalizzata per fare qualcosa di simile a entrambe le operazioni.

0

Non esiste una soluzione che rispetti il ​​contratto Elenco e nessuna delle implementazioni esistenti di elenco consente di fornire un comparatore. Il contratto Elenco definisce il comportamento dell'elenco in termini del metodo equals(Object)10 di ciascun elemento.

Il suggerimento di utilizzare TreeSet con diversi comparatori è anche una violazione del contratto se il metodo del comparatore compare non è coerente con il metodo equals(Object)10 di ciascun elemento.

In pratica potrebbe essere necessario implementare le proprie classi di elenchi. Potresti renderlo un'implementazione List che non segue strettamente il contratto List, ma devi fare attenzione che questo non infranga altri metodi/classi di libreria.

0

Se non si desidera programmare le operazioni Preparatevi e non ti dispiace sprecare alcune risorse di CPU e memoria, si potrebbe:

  • costrutto WrappedPojo s in base alla tua GenericPojo s
  • dare le opportune WrappedPojo implementazioni di equals()
  • creare nuove liste del tipo appropriato di WrappedPojo per fare l'operazione su
  • copia i GenericPojo contenuti nei contenitori originali (se necessario) al termine dell'operazione.

Brutto ma semplice.

0

si poteva tenere tutto questo negli oggetti di dominio dal seguente approccio:

  1. Implementare equals( ... ) su GenericPojo basano solo su id.
  2. Definire WrappedPojo come wrapper attorno a GenericPojo con uno equals( ... ) basato sui campi aggiuntivi GenericPojo.
  3. Per il secondo caso di utilizzo, utilizzare un elenco di istanze spostate.

Suggerisco che il problema principale sta cercando di avere una sola classe dominio con differenti definizioni di uguaglianza.

+0

Il POJO di base non è uno di quelli su cui ho il controllo, forse una soluzione di wrapper è più appropriata per quello che sto cercando di realizzare –

0

Entrambe le operazioni che si sta tentando di eseguire sono funzionali, sebbene Java non le supporti molto bene e probabilmente le scriverà in un modo molto diverso. Potrebbe essere necessario rivedere ciò che si sta cercando di raggiungere per soddisfare java.

Quello che state facendo è l'esecuzione di un'operazione su una proiezione del tipo di dati (vale a dire per un sub set di campi)

Le operazioni che si sta utilizzando sono anche impostare operazioni, piuttosto che le operazioni di lista. per esempio. non è possibile prendere un'intersezione di due elenchi (o almeno è necessario definire cosa significa) Rimuovere potrebbe non funzionare esattamente come previsto per l'elenco.

Immagina di avere un metodo che restituisce una raccolta di pojos con solo i campi specificati. Ho scritto una libreria per farlo in modo efficiente con la classe generata dinamicamente in passato, dare un'occhiata a Java funzionale o simile.

public static <Pojo, Pojo2> Set<Pojo2> project(Collection<Pojo> collection, 
     String... fieldsToRetain); 

Lista1 - Lista2 (dove le classi GenericPojo sono uguali se solo gli ID sono uguali)

Set<PojoWithId> setOfIds = project(list1, "id") 
setOfIds.retainAll(project(list2, "id")); 

Intersect di Lista1 e Lista2 (dove ID, indirizzo, città, paese, ma non extraDetails di GenericPojo sono uguali)

Set<PojoWithThreeFields> intersection = project(list1, "id", "address", "city", "country"); 
intersection.retainAll(project(list2, "id", "address", "city", "country")); 
Problemi correlati