Domanda

Mi piacerebbe avere un SortedSet delle collezioni (si imposta, in questo caso, ma non necessariamente in generale), che le specie di dimensioni Collection. Questo sembra violare il divieto di avere il comparatore essere coerente con equals () -. Vale a dire, due collezioni possono essere disuguale (avendo elementi diversi), ma confrontare allo stesso valore (perché hanno lo stesso numero di elementi)

fittiziamente, potrei anche mettere in modi comparatore per ordinare gruppi di uguali dimensioni, ma l'uso del genere non avrei approfittare di questo, e non c'è davvero un modo utile + intuitivo per confrontare le collezioni di uguali dimensioni (almeno, nel mio caso particolare), in modo tale che sembra uno spreco.

Questo caso di incoerenza sembrare un problema?

È stato utile?

Soluzione

Come ChssPly76 ha scritto in un commento, è possibile utilizzare hashCode per decidere la chiamata compareTo nel caso in cui due collezioni hanno la stessa dimensione, ma non sono uguali. Questo funziona bene, tranne in rari casi in cui si dispone di due collezioni con le stesse dimensioni, non sono uguali, ma hanno lo stesso hashCode. Certo, le probabilità che questo accada sono piuttosto piccole, ma è concepibile. Se si vuole essere molto attenti, invece di hashCode, utilizzare al posto System.identityHashCode. Questo dovrebbe dare un numero unico per ogni collezione, e non si dovrebbe ottenere le collisioni.

Alla fine della giornata, questo ti dà la funzionalità di avere le collezioni del Set ordinati per dimensione, con ordine arbitrario nel caso di due collezioni con dimensione corrispondente. Se questo è tutto ciò che serve, non è molto più lento rispetto al solito confronto sarebbe. Se è necessario l'ordine di essere coerenti tra le diverse istanze JVM, questo non funzionerà e dovrete farlo in qualche altro modo.

pseudocodice:

if (a.equals(b)) {
    return 0;
} else if (a.size() > b.size()) {
    return 1;
} else if (b.size() > a.size()) {
    return -1;
} else {
    return System.identityHashCode(a) > System.identityHashCode(b) ? 1 : -1;
}

Altri suggerimenti

SortedSet interfaccia estende Set e quindi devono essere conformi al contratto indicato nella specifica Set.

L'unico modo possibile per raggiungere questo obiettivo è quello di avere il metodo equal() comportamento del vostro elemento essere coerente con il Comparator -. La ragione di ciò è che Set nucleo funziona basato sulla parità, mentre SortedSet opera basata sul confronto

Ad esempio, metodo add() definito nella interfaccia set base specifica che non è possibile aggiungere un elemento al dispositivo se non v'è già un elemento il cui metodo equal() sarebbe tornato vero con questo nuovo elemento come argomento. Beh, SortedSet non usa equal(), utilizza compareTo(). Quindi, se le vostre dichiarazioni compareTo() false vostro elemento verrà aggiunto anche se equals() dovessimo tornare true, rompendo così il contratto Set.

Niente di tutto questo è un pratica problema di per sé, tuttavia. comportamento SortedSet è sempre coerente, anche se compare() vs equals() non lo sono.

  

Questo sembra violare il divieto   per avere il comparatore essere coerente   con equals () - vale a dire, due collezioni   può essere disuguale (avendo differente   elementi), ma confronto alla stessa   valore (perché hanno la stessa   numero di elementi).

Non v'è alcun obbligo, né dichiarato (nel Javadoc) o implicita, che un Comparator essere coerente con l'implementazione di un oggetto di boolean equals(Object).

Si noti che Comparable e Comparator sono interfacce distinte con scopi diversi. Comparable viene utilizzato per definire un ordine di 'naturale' per una classe. In tale contesto, sarebbe una cattiva idea per equals e compateTo incoerente. Al contrario, un Comparator viene utilizzato quando si desidera utilizzare un ordine diverso per l'ordine naturale di una classe.

EDIT:. Ecco il punto completo dal Javadoc per SortedSet

  

Si noti che l'ordinamento mantenuto da un   set ordinato (anche un esplicito   comparatore è previsto) deve essere   coerente con eguali se l'ordinato   set è quello di attuare correttamente il Set   interfaccia. (Vedere la Paragonabile   interfaccia o comparatore interfaccia per   una definizione precisa di coerenza   con eguali.) Questo è così perché il   Set interfaccia è definita in termini di   l'operazione è uguale, ma un ordinato   set esegue tutti i confronti di elementi   utilizzando il suo compareTo (o confrontare)   metodo, quindi due elementi che sono   ritenuto uguale con tale metodo, da   punto di vista del set ordinato,   pari. Il comportamento di un insieme ordinato è   ben definito anche se il suo ordine è   incompatibile con eguali; e 'solo   non riesce a rispettare il contratto generale   l'interfaccia Set.

Ho evidenziato la frase finale. Il punto è che una tale SortedSet funzionerà come si sarebbe molto probabilmente si aspetterebbe, ma il comportamento di alcune operazioni non corrispondere esattamente alla specifica Set ... perché la specifica definisce il loro comportamento in termini di metodo equals.

Quindi, in realtà, non vi un requisito dichiarato per consistenza (mio errore), ma le conseguenze di ignorare non sono così male come si potrebbe pensare. Naturalmente, spetta a decidere se si dovrebbe fare questo. A mio avviso, dovrebbe essere OK, a condizione che si commenta il codice a fondo e assicurarsi che la SortedSet non si 'fuga'.

Tuttavia, non è chiaro per me che un comparatore per collezioni che guarda solo a un collezioni "dimensione" è andare a lavorare ... dal punto di vista semantico. Voglio dire, non si vuole veramente dire che tutte le collezioni con (diciamo) 2 elementi sono uguali? Ciò significa che il set può sempre e solo contenere una collezione di qualsiasi dimensione ...

Non v'è alcun motivo per cui un Comparator deve restituire gli stessi risultati equals(). In realtà, l'API Comparator è stata introdotta perché equals() solo non è sufficiente: se si desidera ordinare una raccolta, è necessario sapere se due elementi sono minore o maggiore

.

E 'un po' strano che SortedSet come parte della API standard rompe il contratto definito nell'interfaccia Imposta e utilizza il comparatore per definire l'uguaglianza al posto del metodo equals, ma è così che è.

Se il problema reale è quello di ordinare una collezione di collezioni in base alle dimensioni delle collezioni containted, si sono meglio di una lista, che è possibile ordinare tramite Collections.sort (Lista, comparatore>);

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top