parcourir - treemap java




Pourquoi Java Map ne prolonge-t-il pas la collection? (7)

Exactement, l' interface Map<K,V> extends Set<Map.Entry<K,V>> serait génial!

En fait, s'il implements Map<K,V>, Set<Map.Entry<K,V>> , alors j'ai tendance à être d'accord .. Cela semble même naturel. Mais ça ne marche pas très bien, n'est-ce pas? Disons que nous avons HashMap implements Map<K,V>, Set<Map.Entry<K,V> , LinkedHashMap implements Map<K,V>, Set<Map.Entry<K,V> etc ... c'est tout bien, mais si vous avez entrySet() , personne n'oubliera d'implémenter cette méthode, et vous pouvez être sûr que vous pouvez obtenir entrySet pour n'importe quelle Map, alors que vous ne l'êtes pas si vous espérez que l'implémenteur a implémenté les deux interfaces. .

La raison pour laquelle je ne veux pas avoir d' interface Map<K,V> extends Set<Map.Entry<K,V>> est simplement, car il y aura plus de méthodes. Et après tout, ce sont des choses différentes, n'est-ce pas? Aussi très pratique, si je frappe la map. dans IDE, je ne veux pas voir .remove(Object obj) , et .remove(Map.Entry<K,V> entry) parce que je ne peux pas faire hit ctrl+space, r, return et être fait avec .

J'ai été surpris par le fait que Map<?,?> N'est pas une Collection<?> .

Je pensais que cela aurait beaucoup de sens si elle était déclarée comme telle:

public interface Map<K,V> extends Collection<Map.Entry<K,V>>

Après tout, une Map<K,V> est une collection de Map.Entry<K,V> , n'est-ce pas?

Alors y a-t-il une bonne raison pour que ce ne soit pas mis en œuvre en tant que tel?

Merci à Cletus pour une réponse qui fait autorité, mais je me demande encore pourquoi, si vous pouvez déjà voir une Map<K,V> comme Set<Map.Entries<K,V>> (via entrySet() ), elle ne le fait pas N'étendez pas cette interface à la place.

Si une Map est une Collection , quels sont les éléments? La seule réponse raisonnable est "Les paires clé-valeur"

Exactement, l' interface Map<K,V> extends Set<Map.Entry<K,V>> serait génial!

mais ceci fournit une abstraction de Map très limitée (et pas particulièrement utile).

Mais si c'est le cas alors pourquoi entrySet est- entrySet spécifié par l'interface? Cela doit être utile d'une façon ou d'une autre (et je pense qu'il est facile de plaider pour cette position!).

Vous ne pouvez pas demander à quelle valeur une clé donnée correspond, ni supprimer l'entrée pour une clé donnée sans savoir à quelle valeur elle correspond.

Je ne dis pas que c'est tout pour Map ! Il peut et devrait garder toutes les autres méthodes (sauf entrySet , qui est redondant maintenant)!


À partir de la FAQ sur la conception de l'API Java Collections :

Pourquoi la carte ne s'étend-elle pas à la collection?

C'était par conception. Nous estimons que les mappages ne sont pas des collections et que les collections ne sont pas des mappages. Ainsi, il est peu logique pour Map d'étendre l'interface de collection (ou vice versa).

Si une carte est une collection, quels sont les éléments? La seule réponse raisonnable est "paires clé-valeur", mais cela fournit une abstraction de carte très limitée (et pas particulièrement utile). Vous ne pouvez pas demander à quelle valeur une clé donnée correspond, ni supprimer l'entrée pour une clé donnée sans savoir à quelle valeur elle correspond.

Collection pourrait être faite pour étendre la carte, mais cela soulève la question: quelles sont les clés? Il n'y a pas de réponse vraiment satisfaisante, et forcer l'un mène à une interface non naturelle.

Les cartes peuvent être vues comme des collections (de clés, de valeurs ou de paires), et ce fait est reflété dans les trois «opérations de vue de collection» sur Maps (keySet, entrySet et valeurs). Bien qu'il soit, en principe, possible d'afficher une liste en tant qu'index de mappage d'éléments cartographiques, cela a la désagréable propriété que la suppression d'un élément de la liste modifie la clé associée à chaque élément avant l'élément supprimé. C'est pourquoi nous n'avons pas d'opération d'affichage de carte sur les listes.

Mise à jour: Je pense que la citation répond à la plupart des questions. Il vaut la peine de souligner la partie sur une collection d'entrées n'étant pas une abstraction particulièrement utile. Par exemple:

Set<Map.Entry<String,String>>

permettrait:

set.add(entry("hello", "world"));
set.add(entry("hello", "world 2");

(en supposant une méthode entry() qui crée une instance Map.Entry )

Map nécessitent des clés uniques, ce qui serait contraire à cette règle. Ou si vous imposez des clés uniques sur un Set d'entrées, ce n'est pas vraiment un Set au sens général. C'est un Set avec d'autres restrictions.

On pourrait dire que la relation equals() / hashCode() pour Map.Entry était purement sur la clé, mais même cela a des problèmes. Plus important encore, cela ajoute-t-il vraiment de la valeur? Vous pouvez trouver cette abstraction se décompose une fois que vous commencez à regarder les cas de coin.

Il est à noter que le HashSet est implémenté en tant que HashMap , et non l'inverse. Ceci est purement un détail de mise en œuvre mais est néanmoins intéressant.

La principale raison pour laquelle entrySet() existe est de simplifier la traversée afin que vous n'ayez pas à parcourir les clés et ensuite faire une recherche de la clé. Ne le prenez pas comme preuve prima facie qu'une Map devrait être un Set d'entrées (imho).


Direct et simple. Collection est une interface qui n'attend qu'un seul objet, Where as Map Two.

Collection(Object o);
Map<Object,Object>

Je suppose que le pourquoi est subjective.

En C #, je pense que Dictionary étend ou au moins implémente une collection:

public class Dictionary<TKey, TValue> : IDictionary<TKey, TValue>, 
    ICollection<KeyValuePair<TKey, TValue>>, IEnumerable<KeyValuePair<TKey, TValue>>, 
    IDictionary, ICollection, IEnumerable, ISerializable, IDeserializationCallback

Au Pharo Smalltak aussi:

Collection subclass: #Set
Set subclass: #Dictionary

Mais il y a une asymétrie avec certaines méthodes. Par exemple, collect: will prend l'association (l'équivalent d'une entrée), while do: prend les valeurs. Ils fournissent une autre méthode keysAndValuesDo: pour itérer le dictionnaire par entrée. Add: prend une association, mais remove: a été "supprimé":

remove: anObject
self shouldNotImplement 

Donc, c'est définitivement faisable, mais conduit à d'autres problèmes concernant la hiérarchie des classes.

Ce qui est meilleur est subjectif.


Les collections Java sont cassées. Il y a une interface manquante, celle de Relation. Par conséquent, Map extends Relation extends Set. Les relations (également appelées multi-cartes) ont des paires nom-valeur uniques. Maps (aka "Fonctions"), ont des noms uniques (ou des clés) qui bien sûr mapper aux valeurs. Les séquences étendent Maps (où chaque clé est un entier> 0). Les sacs (ou multi-sets) étendent Maps (où chaque clé est un élément et chaque valeur est le nombre de fois que l'élément apparaît dans le sac).

Cette structure permettrait l'intersection, l'union etc. d'une gamme de «collections». Par conséquent, la hiérarchie devrait être:

                                Set

                                 |

                              Relation

                                 |

                                Map

                                / \

                             Bag Sequence

Sun / Oracle / Java ppl - merci de bien l'avoir la prochaine fois. Merci.


Si vous regardez la structure de données respective, vous pouvez facilement deviner pourquoi Map ne fait pas partie de Collection . Chaque Collection stocke une seule valeur où une Map stocke une paire clé-valeur. Les méthodes de l'interface de Collection sont donc incompatibles avec l'interface de Map . Par exemple, dans Collection nous avons add(Object o) . Quelle serait une telle mise en œuvre dans Map . Cela n'a pas de sens d'avoir une telle méthode dans Map . Au lieu de cela, nous avons une méthode put(key,value) dans Map .

Le même argument addAll() aux addAll() , remove() et removeAll() . Donc, la principale raison est la différence dans la façon dont les données sont stockées dans la Map et la Collection . Aussi, si vous vous rappelez que l'interface de Collection implémenté une interface Iterable , c'est-à-dire que toute interface avec la méthode .iterator() devrait renvoyer un itérateur qui doit nous permettre de parcourir les valeurs stockées dans la Collection . Maintenant, qu'est-ce qu'une telle méthode retournerait pour une Map ? Un itérateur de clé ou un itérateur de valeur? Cela n'a pas de sens non plus.

Il existe des façons de parcourir les clés et les valeurs dans une Map et c'est ainsi que cela fait partie du cadre de Collection .


Map<K,V> ne doit pas étendre Set<Map.Entry<K,V>> car:

  • Vous ne pouvez pas ajouter différents Map.Entry avec la même clé à la même Map , mais
  • Vous pouvez ajouter différents Map.Entry avec la même clé au même Set<Map.Entry> .




collections