In Java, perché fa (unsorted) Set implement Iterable, ma SortedMap no?

7

Ci sono due aspetti di questa domanda che ho ritenuto fossero troppo strettamente correlati a porre domande separate.

  1. Perché SortedMap non implementa Iterable<Map.Entry<K,V>> ?

Se è necessario eseguire un'azione su ogni coppia chiave-valore in una mappa, iterare su entrySet () sembra la strada da percorrere. Quindi, perché non fornire un metodo diretto iterator () su SortedMap? A meno che non siate preoccupati che l'ordine di iterazione sia incoerente in una HashMap. Il che mi porta a:

  1. L'implementazione di Iterable implica un ordine stabile?

L'iterazione su una raccolta ordinata (Elenco, SortedMap, SortedSet) è un ottimo modo per implementare in modo affidabile equals () (vedi Nota 1) e fare altre cose che devono produrre lo stesso risultato ogni volta. L'iterazione su una serie o mappa non ordinata potrebbe produrre ordini diversi se la chiami più volte, quindi non è adatta a tali scopi. Soprattutto se stai confrontando HashSets o HashMaps - due di loro potrebbero contenere gli stessi oggetti, ma l'ordine dei loro iteratori sarebbe diverso.

Suppongo che ci siano 2 aspetti in queste domande:

  1. Quali sono i motivi storici di queste decisioni di progettazione?

  2. Se lo fai di nuovo oggi, ci sono risposte corrette a queste domande? Forse OrderedIterable dovrebbe estendere Iterable per garantire l'ordine?

Note:

  1. Inizialmente avevo suggerito che era necessario un ordinamento affidabile per implementare hashCode (), ma se si sommano tutti gli hashcode, risulta che non è necessario un ordinamento affidabile se l'algoritmo di hashing è commutativo. L'addizione è comunemente usata per hashCode ed è commutativa: a + b = b + a e B. anche con overflow, l'addizione è ancora commutativa in modo che un + Integer.MAX_VALUE = Integer.MAX_VALUE + a. Hai ancora bisogno di un ordine affidabile per implementare equals () in modo da poter confrontare il primo elemento di uno con il primo elemento dell'altro, ecc.

P.S.

Questa domanda riguarda le interfacce Iterable , Set , SortedSet , Map e SortedMap . Va bene visualizzare altre interfacce come esempi, ma Non penso che l'interfaccia Collection sia rilevante per questa domanda. È stravagante e ha il potenziale per essere una distrazione.

    
posta GlenPeterson 04.06.2015 - 15:59
fonte

1 risposta

11

Anche se è corretto da un punto di vista strettamente tecnico dire che Set implementa Iterable , ma SortedMap no, non è una domanda molto utile da chiedere. Una domanda più utile da porsi è se entrambe le classi offrono l'interfaccia Iterable , e sicuramente entrambe lo fanno.

Come sai, ci sono tre modi per offrire un'interfaccia:

  1. Implementandolo esplicitamente utilizzando la parola chiave implements .
  2. Implementando un'interfaccia che estende l'interfaccia in questione.
  3. Esponendo una funzione che restituisce l'interfaccia in questione.

Set è dichiarato come segue: public interface Set<E> extends Collection<E> {... quindi, come puoi vedere, Set non implementa direttamente Iterable , lo implementa solo indirettamente, in virtù dell'implementazione di Collection , che estende Iterable .

Ora, SortedMap vorrebbe implementare anche Iterable indirettamente, proprio come Set , se stava implementando Collection , ma non lo fa nemmeno. Invece, espone una funzione entrySet() , che restituisce un Collection , che estende Iterable .

Quindi, puoi avere il tanto desiderato Iterable in entrambi i casi.

Se vuoi insistere sulla questione strettamente tecnica del perché Set (indirettamente) implementa Iterable , ma SortedMap lo offre tramite una funzione, la risposta è che i progettisti del runtime in linguaggio java hanno fatto la decisione molto tempo fa di astenersi dal fare ampio uso di interfacce estendendo altre interfacce. Ecco perché Map<K,V> non estende Collection<Map.Entry<K,V>> , offrendo invece un metodo entrySet() .

Avrebbero potuto fare il contrario, e in effetti i progettisti del runtime in linguaggio C # hanno scelto di andare nell'altro modo, quindi IDictionary<K,V> estende ICollection<KeyValuePair<K,V>> .

Ho sperimentato in entrambi i modi e non sono ancora arrivato a una decisione definitiva su quale sia il migliore. Sembrano semplicemente due modi diversi per realizzare la stessa cosa.

L'implementazione di Iterator non implica un ordinamento stabile, come tu sembri capire (e quindi non mi è chiaro dove la tua domanda è a tale riguardo.) Puoi iterare su una mappa non ordinata, nel qual caso nessuno può dire quale sarà l'ordine degli articoli, e puoi inserire un elemento nella mappa e ripetere l'iterazione, nel qual caso l'ordine degli articoli potrebbe essere completamente diverso dal tempo precedente. (Non solo diverso per un articolo: tutti gli articoli potrebbero sembrare riorganizzati.)

Non è necessaria un'interfaccia OrderedIterable perché la sua firma sarebbe identica a Iterable . (E non farmi iniziare sulla scelta delle persone java di introdurre un Set oltre a Collection .) Puoi solo invocare OrderedMap.entrySet() , che la documentazione promette restituirà un ordinato set, il che significa che il Iterator di quel set produrrà sempre elementi in ordine.

    
risposta data 04.06.2015 - 16:13
fonte

Leggi altre domande sui tag