public Collection<V> values() { if (values == null) { values = new AbstractCollection<V>() { public Iterator<V> iterator() { return new Iterator<V>() { private Iterator<Entry<K,V>> i = entrySet().iterator(); public boolean hasNext() { return i.hasNext(); } public V next() { return i.next().getValue(); } public void remove() { i.remove(); } }; } public int size() { return AbstractMap.this.size(); } public boolean isEmpty() { return AbstractMap.this.isEmpty(); } public void clear() { AbstractMap.this.clear(); } public boolean contains(Object v) { return AbstractMap.this.containsValue(v); } }; } return values; }
3 Réponses :
Je ne sais pas quelle version de Java vous utilisez, mais je ne vois pas d'instance de classe abstraite renvoyée par values ()
. Il renvoie une instance de TreeMap.Values
, qui est une classe qui étend AbstractCollection
.
Quant à savoir pourquoi il ne renvoie pas un Set
- c'est simplement dû au fait que la collection de valeurs peut contenir des doublons, ce qu'un Set
ne permet pas .
Une Liste
n'est pas non plus idéale, car elle impliquerait que les valeurs sont ordonnées, ce qui n'est pas vrai pour toutes les implémentations de Map
(telles que HashMap code>).
BTW, au lieu d'imprimer des choses comme map.values () instanceof Set
, vous auriez pu simplement imprimer map.value (). getClass (). getName ()
pour voir la classe d'implémentation réelle.
Cela vient de java8
.
Une raison simplement en regardant l'implémentation: contains
et iterator
regardent tous les deux le contenu actuel de la carte par opposition au contenu de la carte lorsque values ()
a été appelée.
Si vous appelez values ()
puis modifiez quelque chose dans la carte, ce changement sera reflété dans la Collection
renvoyée à l'origine depuis values()
.
Map<String, String> map = new HashMap<String, String>(); map.put("some", "thing"); Collection<String> values = map.values(); System.out.println(values.size()); // 1 map.put("foo", "bar"); System.out.println(values.size()); // 2
Hashset utilise HashMap en interne, il n'y a donc pas beaucoup de copie des valeurs dans le scénario.
Vous pouvez voir le lien associé pour en savoir plus. Lien de référence .
d'où vient la collection abstraite, voici quelques informations connexes extraites de Java Doc:
1] Cette classe fournit une implémentation squelettique de la Collection interface, afin de minimiser l'effort requis pour implémenter cette interface.
2] Pour implémenter une collection non modifiable, le programmeur n'a qu'à
étendre cette classe et fournir des implémentations pour le iterator
et
Méthodes size
. (L'itérateur renvoyé par le iterator
La méthode doit implémenter hasNext
et next
.
3] Pour implémenter une collection modifiable, le programmeur doit en plus
écraser la méthode add de cette classe (qui
UnsupportedOperationException
) et l'itérateur renvoyé par le
La méthode iterator doit en plus implémenter son remove
méthode.
J'espère que cela vous a été utile.
De cette façon, la représentation interne est rendue accessible sans avoir à copier la carte / l'ensemble dans une nouvelle collection ou à vous rendre dépendant des détails d'implémentation.