Java Collection Interface
The root Collection interface in Java and the contract every list, set, and queue inherits from it.
Java Collection Interface
java.util.Collection<E> is the root of the part of the framework that holds individual elements — every List, Set, Queue, and Deque implements it (the only family that doesn't is Map, whose elements are entries, not single values). Everything you can do "no matter which group it is" — add, remove, ask contains, iterate, count, convert to array, stream — is declared here. This chapter is the contract: the methods you can rely on for any collection, the few that may throw, and the iteration model every implementation inherits.
The hierarchy at a glance
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 extends Iterable<E>, which is why every collection works with the for-each loop. The two specialisations of Collection — Set and Queue — refine the contract; Map is its own root.
Core methods every collection has
Below is the full set of instance methods on Collection, grouped by purpose. Memorise the categories rather than the list — once you know there's a method called removeIf you can find it.
Size and emptiness
int size()— element count.boolean isEmpty()—size() == 0but often faster.
Adding
boolean add(E e)— adds one element. Returnstrueif the collection changed. (ASetreturnsfalsefor a duplicate.)boolean addAll(Collection<? extends E> c)— adds every element ofc.
Removing
boolean remove(Object o)— removes one occurrence ofo.boolean removeAll(Collection<?> c)— removes every element that appears inc.boolean retainAll(Collection<?> c)— keeps only the elements inc(intersection).boolean removeIf(Predicate<? super E> filter)— removes every element that matches the predicate. The cleanest way to filter in place.void clear()— empties the collection.
Querying
boolean contains(Object o)— membership test.boolean containsAll(Collection<?> c)— subset test.
Iteration and bulk views
Iterator<E> iterator()— the underlying iterator; whatfor-eachuses.Stream<E> stream()/parallelStream()— open aStreamover the elements.void forEach(Consumer<? super E> action)— inherited fromIterable. The functional iteration form.
Array conversion
Object[] toArray()<T> T[] toArray(T[] a)and the newer<T> T[] toArray(IntFunction<T[]> generator)(Java 11+) — typed array.
That's the whole interface. Every list, set, and queue you'll meet in this part is just a different implementation of those methods plus a few of its own.
Equality and equals / hashCode
Collection.equals(Object) is not defined on the root — each sub-interface specifies what equality means for it. List requires same-order same-elements; Set requires same-elements regardless of order; Queue doesn't define equals at all (a LinkedList queue and an ArrayDeque queue with the same content are not equal because the comparison falls back to identity). Don't compare collections across families and expect symmetry.
Elements stored in a Collection must have a sensible equals / hashCode if you want contains, remove, and (for hash-based collections) lookup to behave. We covered the contract in the equals and hashCode chapter — that's the prerequisite for using Set and Map with your own classes.
Optional operations
Some collections are unmodifiable — List.of(1,2,3), Collections.unmodifiableList(list), the views returned from Map.keySet() on certain implementations, etc. They still implement Collection, but calling add, remove, clear, or any mutating method throws UnsupportedOperationException. The Javadoc calls these "optional operations." It's the closest Java has to a runtime opt-out for parts of an interface; the price is that the compiler can't catch the mistake — you find out on the first throw.
A safe rule: if you didn't construct the collection, treat it as possibly unmodifiable. If you need a mutable copy, do new ArrayList<>(received) first.
Iteration: three forms, one underlying mechanism
Every collection supports three iteration styles, and all three end up calling 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
}Why forms 1 and 3 still both matter: the for-each loop can't modify the underlying collection without throwing ConcurrentModificationException. When you need to remove while iterating, you reach for the explicit Iterator. The Iterators chapter later in this part covers the protocol in detail.
Set algebra with bulk operations
The bulk operations turn a collection into a set-algebra calculator (independent of whether it's a Set — they work on List too):
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)); // differenceThese are the safe, dependency-free way to express "keep only the items also in b" without writing a loop. They modify the receiver — if you need an immutable result, copy first.
A worked example: every method, side by side
The program below exercises each category of Collection method against the same ArrayList, so you can see them in one place and watch the contract play out.
Two things worth pointing out from the output:
remove(\"red\")only removed the first occurrence — that's the contract onCollection. To remove every match, useremoveIf(you saw it next, removing every word longer than four characters).- The
UnsupportedOperationExceptionfromfrozen.add(\"d\")is the "optional operations" rule in action.frozenimplementsCollection, so the call compiles. The implementation chose not to support it, and you learn that at runtime.
What's next
Collection is the abstract contract. The first concrete refinement you'll meet is the one that adds order and indexing — the List interface. That's where indexed access, sub-lists, and order-preserving operations enter the picture.
Practice
You have a `Collection<String>` and want to remove every element whose length is greater than four. Which approach is the idiomatic, single-statement way?