Interface Collection en Java
L'interface Collection racine en Java et le contrat hérité par chaque liste, ensemble et file d'attente.
java.util.Collection<E> est la racine de la partie du framework qui contient des éléments individuels — chaque List, Set, Queue et Deque l'implémente (la seule famille qui ne le fait pas est Map, dont les éléments sont des entrées, pas des valeurs uniques). Tout ce que vous pouvez faire « quel que soit le groupe » — ajouter, supprimer, demander contains, itérer, compter, convertir en tableau, streamer — est déclaré ici. Ce chapitre est le contrat : les méthodes sur lesquelles vous pouvez compter pour n'importe quelle collection, les quelques-unes qui peuvent lever des exceptions, et le modèle d'itération que chaque implémentation hérite.
La hiérarchie en un coup d'œil
Iterable<E>
└── Collection<E>
├── List<E> — ordered, indexed, duplicates allowed
├── Set<E> — no duplicates
│ └── SortedSet<E> → NavigableSet<E>
└── Queue<E> — "next in line"
└── Deque<E> — double-ended queueCollection étend Iterable<E>, c'est pourquoi chaque collection fonctionne avec la boucle for-each. Les deux spécialisations de Collection — Set et Queue — affinent le contrat ; Map est sa propre racine.
Méthodes de base disponibles dans toute collection
Voici l'ensemble complet des méthodes d'instance sur Collection, regroupées par objectif. Mémorisez les catégories plutôt que la liste — une fois que vous savez qu'il existe une méthode appelée removeIf, vous pouvez la retrouver.
Taille et vacuité
int size()— nombre d'éléments.boolean isEmpty()—size() == 0mais souvent plus rapide.
Ajout
boolean add(E e)— ajoute un élément. Retournetruesi la collection a changé. (UnSetretournefalsepour un doublon.)boolean addAll(Collection<? extends E> c)— ajoute chaque élément dec.
Suppression
boolean remove(Object o)— supprime une occurrence deo.boolean removeAll(Collection<?> c)— supprime chaque élément qui apparaît dansc.boolean retainAll(Collection<?> c)— conserve uniquement les éléments présents dansc(intersection).boolean removeIf(Predicate<? super E> filter)— supprime chaque élément correspondant au prédicat. La façon la plus propre de filtrer en place.void clear()— vide la collection.
Interrogation
boolean contains(Object o)— test d'appartenance.boolean containsAll(Collection<?> c)— test de sous-ensemble.
Itération et vues groupées
Iterator<E> iterator()— l'itérateur sous-jacent ; ce qu'utilisefor-each.Stream<E> stream()/parallelStream()— ouvre unStreamsur les éléments.void forEach(Consumer<? super E> action)— héritée deIterable. La forme d'itération fonctionnelle.
Conversion en tableau
Object[] toArray()<T> T[] toArray(T[] a)et le plus récent<T> T[] toArray(IntFunction<T[]> generator)(Java 11+) — tableau typé.
C'est l'intégralité de l'interface. Chaque liste, ensemble et file d'attente que vous rencontrerez dans cette partie n'est qu'une implémentation différente de ces méthodes plus quelques-unes qui lui sont propres.
Égalité et equals / hashCode
Collection.equals(Object) n'est pas défini à la racine — chaque sous-interface spécifie ce que l'égalité signifie pour elle. List exige les mêmes éléments dans le même ordre ; Set exige les mêmes éléments indépendamment de l'ordre ; Queue ne définit pas equals du tout (une file LinkedList et une file ArrayDeque ayant le même contenu ne sont pas égales car la comparaison revient à l'identité d'objet). Ne comparez pas des collections entre familles différentes en attendant la symétrie.
Les éléments stockés dans une Collection doivent avoir des equals / hashCode cohérents si vous voulez que contains, remove et (pour les collections basées sur le hachage) les recherches fonctionnent correctement. Nous avons couvert le contrat dans le chapitre equals et hashCode — c'est le prérequis pour utiliser Set et Map avec vos propres classes.
Opérations optionnelles
Certaines collections sont non modifiables — List.of(1,2,3), Collections.unmodifiableList(list), les vues retournées par Map.keySet() sur certaines implémentations, etc. Elles implémentent toujours Collection, mais appeler add, remove, clear, ou toute méthode de mutation lève UnsupportedOperationException. La Javadoc appelle celles-ci des « opérations optionnelles ». C'est ce qui se rapproche le plus, en Java, d'une exclusion à l'exécution de parties d'une interface ; le prix est que le compilateur ne peut pas détecter l'erreur — vous le découvrez à la première exception levée.
Une règle sûre : si vous n'avez pas construit la collection, traitez-la comme potentiellement non modifiable. Si vous avez besoin d'une copie mutable, faites d'abord new ArrayList<>(received).
Itération : trois formes, un mécanisme sous-jacent
Chaque collection prend en charge trois styles d'itération, et tous trois finissent par appeler iterator() :
Collection<String> names = List.of("Ada", "Linus", "Grace");
// 1. for-each — the everyday form
for (String n : names) System.out.println(n);
// 2. forEach with a lambda — declarative
names.forEach(System.out::println);
// 3. Iterator — when you need to remove during iteration
Iterator<String> it = names.iterator();
while (it.hasNext()) {
String s = it.next();
if (s.startsWith("L")) it.remove(); // safe; for-each can't do this
}Pourquoi les formes 1 et 3 ont encore leur importance : la boucle for-each ne peut pas modifier la collection sous-jacente sans lever ConcurrentModificationException. Lorsque vous devez supprimer pendant l'itération, vous utilisez l'Iterator explicite. Le chapitre Iterators plus loin dans cette partie couvre le protocole en détail.
Algèbre d'ensembles avec les opérations groupées
Les opérations groupées transforment une collection en calculatrice d'algèbre d'ensembles (indépendamment du fait qu'il s'agisse d'un Set — elles fonctionnent aussi sur List) :
Collection<Integer> a = new ArrayList<>(List.of(1, 2, 3, 4));
Collection<Integer> b = List.of(3, 4, 5);
a.addAll(b); // union (multiset)
a.retainAll(List.of(3, 4)); // intersection
a.removeAll(List.of(3)); // differenceCe sont les façons sûres et sans dépendances d'exprimer « ne garder que les éléments présents dans b » sans écrire de boucle. Elles modifient le récepteur — si vous avez besoin d'un résultat immuable, copiez d'abord.
Un exemple complet : toutes les méthodes côte à côte
Le programme ci-dessous exerce chaque catégorie de méthode de Collection sur le même ArrayList, afin que vous puissiez les voir en un seul endroit et observer le contrat en action.
Deux points à noter à partir de la sortie :
remove("red")n'a supprimé que la première occurrence — c'est le contrat surCollection. Pour supprimer chaque correspondance, utilisezremoveIf(vous l'avez vu ensuite, supprimant chaque mot de plus de quatre caractères).- L'
UnsupportedOperationExceptiondefrozen.add("d")est la règle des « opérations optionnelles » en action.frozenimplémenteCollection, donc l'appel compile. L'implémentation a choisi de ne pas le supporter, et vous le découvrez à l'exécution.
Et maintenant
Collection est le contrat abstrait. Le premier raffinement concret que vous rencontrerez est celui qui ajoute l'ordre et l'indexation — l'interface List. C'est là qu'interviennent l'accès indexé, les sous-listes et les opérations préservant l'ordre.