2012-08-26 6 views
17

Object in Java ha hashCode metodo, tuttavia, viene utilizzato solo in contenitori associativi come HashSet o HashMap. Perché è stato progettato in questo modo? L'interfaccia Hashable con il metodo hashCode sembra una soluzione molto più elegante.Perchè non v'è alcuna interfaccia hashable in Java

+0

Perché è necessaria un'interfaccia speciale quando è possibile eseguire l'override in ogni punto e Object è di default una super classe di tutti? – kosa

+2

@Namban La domanda è più di "Perché ogni oggetto ha un metodo hashCode(), quando è usato solo da alcune classi di raccolta java.util. *." cioè perché non c'è, ad es. un'interfaccia ObjectHash, proprio come c'è un'interfaccia comparabile, ecc. – nos

+1

Questo è più di un argomento di discussione che di una domanda, quindi non è proprio adatto per SO. – Keppil

risposta

6

L'argomento principale mi sembra che esista un valore predefinito predefinito hashCode che può essere calcolato per qualsiasi oggetto Java, insieme a uno equals ugualmente definito. Semplicemente non vi è alcuna buona ragione per ritenere questa funzione da tutti gli oggetti, e naturalmente ci sono molti motivi per cui lo non è lo. Quindi è un gioco da ragazzi nel mio libro.

+0

Non penso che affermi che dovrebbe esserci una procedura generale per ottenere 'hashCode'; sta affermando che 'hashCode' dovrebbe essere reso parte di qualche interfaccia' Hashable' e non lasciata in 'Object'. – oldrinb

+0

@veer sì, esattamente quello – karlicoss

+0

@veer OK, ora vedo. Ho letto male. Ma ancora, è solo una ragione leggermente diversa allora. –

0

Questa domanda viene richiesta come duplicata da un'altra che chiede il motivo per cui non esiste un'interfaccia che si comporta come Comparator (a differenza di Comparable) ma per l'hashing. .NET include una tale interfaccia, chiamata IEqualityComparer, e sembrerebbe che anche Java potrebbe. Così com'è, se qualcuno vuole ad es. avere una raccolta Java che ad es. associa le stringhe ad altri oggetti in modo non sensibile alle maiuscole e minuscole (forse l'uso più comune di IEqualityComparer) è necessario disporre le stringhe negli oggetti i cui metodi hashCode e equals agiscono in base a una distinzione tra maiuscole e minuscole.

Ho il sospetto che il grosso problema è che mentre un'interfaccia "equalityComparer" potrebbe essere conveniente, in molti casi testare in modo efficiente una relazione di equivalenza richiederebbe informazioni di cache. Ad esempio, mentre una funzione di hash stringa senza distinzione tra maiuscole e minuscole potrebbe eseguire una copia solo in maiuscolo della stringa passata e chiamare hashCode su quello, sarebbe difficile evitare che ogni richiesta per l'hashcode di una stringa particolare ripeta la conversione in maiuscolo e l'hashing di quel valore maiuscolo. Al contrario, un oggetto "stringa senza distinzione tra maiuscole e minuscole" potrebbe includere campi per una copia solo in maiuscolo della stringa, che dovrebbe essere generata solo una volta per l'istanza.

Un EqualityComparer potrebbe raggiungere prestazioni ragionevole se comprendeva qualcosa come un WeakHashMap<string,string> per convertire le stringhe prime in maiuscolo-solo le stringhe, ma un tale progetto sarebbe o richiedere diversi thread di utilizzare diversi EqualityComparer casi, nonostante la mancanza di stato visibile esternamente, o altrimenti richiedono il codice di blocco e sincronizzazione di roaming delle prestazioni anche in scenari a thread singolo.

Per inciso, un secondo problema che si presenta con le interfacce in stile comparatore è che un tipo di raccolta che utilizza un comparatore fornito esternamente (sia che si confronti per rango o uguaglianza) è che il comparatore stesso diventa parte dello stato della classe che lo usa Se le tabelle hash utilizzano diverse istanze di EqualityComparer, potrebbe non esserci modo di sapere che possono essere tranquillamente considerate equivalenti, anche se i due comparatori si comporterebbero in modo identico in tutte le circostanze.

0

A che serve avere un'interfaccia che ogni oggetto implementa comunque da inheritage? Poiché Object lo implementa e si suppone che sia lavabile, dovrebbe avere implements Hashable nella sua dichiarazione e tutte le altre classi lo erediteranno perché sono sottoclassi di Object. Avere un'interfaccia Hashable direbbe semplicemente l'ovvio.

+0

Sotto lo stesso pensiero possiamo chiederci, a che serve avere due metodi che ogni oggetto ha, ma mai usato? E quando alla fine vengono utilizzati chiamando solo un metodo, ma non l'altro, il codice del chiamante fallisce in modo spettacolare. Quindi cosa giustifica questa decisione progettuale? –