1. Introduction
Once, we already discussed “infinite arrays” — lists. Let’s deepen our knowledge and once again ask what a “classic” array is. If you look closely, it’s like a toolbox with a fixed number of compartments. Suppose the box has 10 slots. You’ve got an 11th tool — now what? You’ll have to buy a new box! A traditional array has a fixed size, and once created, its length won’t change.
If you need to add or remove an element, you have to create a new array and copy the data manually. In an array, you can find an element by index quickly and easily, but inserting an element in the middle isn’t just “insert” — it’s “shift everything to the right,” and when deleting — “shift everything to the left.” That’s slow and inconvenient. In addition, an array doesn’t contain any extra “logic”: it just holds a set of slots, and sorting, searching by content, or checking for uniqueness has to be done externally.
Example: a dynamic list of students
Suppose you’re writing an app to track students in a group. At first there are 5 students, then one more arrives, then someone leaves. With an array, it would look like this:
String[] students = new String[5];
students[0] = "Ivan";
students[1] = "Maria";
// and so on...
// Oops, one more student arrived
// We need to create a new array!
String[] newStudents = new String[6];
for (int i = 0; i < students.length; i++) {
newStudents[i] = students[i];
}
newStudents[5] = "Alexey";
students = newStudents;
Convenient? Not really. And if you have to do this a lot? Then you’ll want something more convenient...
2. What is a collection?
A collection is an object that serves as a container for storing a group of other objects (elements). Collections let you add, remove, iterate over elements, and perform other operations: search, sorting, filtering, etc.
In Java, all collections implement or inherit from the Collection interface (or, for mappings — from Map). A collection isn’t just “a random pile of things,” but a structure that provides a convenient, well-thought-out set of methods for working with elements.
Why are collections objects?
Because collections are implemented as classes, which means you can create collections of any objects, combine them, inherit, extend, and use them in your own classes and methods.
Example:
import java.util.ArrayList;
import java.util.List;
List<String> students = new ArrayList<>();
students.add("Ivan");
students.add("Maria");
students.add("Alexey");
Voilà! Now you can add as many students as you like without worrying about the array size.
3. Common tasks collections solve
Collections are a Swiss Army knife for working with data. Here’s what they let you do:
- Store a dynamic list of data: For example, a list of students, tasks in a scheduler, messages in a chat.
- Search and filter: Quickly find an element, check its presence, get all elements that match some condition.
- Sorting: Easily sort elements by the required criterion.
- Removing and adding elements: Insert and remove elements anywhere in the collection without manually copying arrays.
- Grouping by key: For example, a phone book where each name corresponds to a phone number.
- Guarantee uniqueness: For example, the set of all unique words in a text.
Example: a phone book
With an array:
- How do you find a number by name? You have to iterate over the array and compare names.
- How do you add a new pair? You have to expand the array.
- How do you guarantee that names don’t repeat? Even harder.
With a collection:
- Use a Map<String, String> — and everything works out of the box.
4. Overview of the main collection types
In Java, collections fall into three main groups:
| Collection type | Interface/class | What it’s used for |
|---|---|---|
| List | List, ArrayList | Ordered sequence of elements; allows duplicates; index-based access |
| Set | Set, HashSet | Stores only unique elements; order is not guaranteed |
| Map | Map, HashMap | Stores key–value pairs; fast lookup by key |
Lists (List)
- Ordered collections; allow duplicates.
- You can get an element by index.
- Examples: ArrayList, LinkedList.
Sets (Set)
- Store only unique elements.
- No index-based access.
- Examples: HashSet, TreeSet.
Maps (Map)
- Store key–value pairs.
- Fast lookup by key.
- Examples: HashMap, TreeMap.
Visual diagram (very simplified):
+------------------+ +-------------------+ +---------------------+
| List | | Set | | Map |
|------------------| |-------------------| |---------------------|
| [a, b, c, d, a] | | {a, b, c, d} | | {a=1, b=2, c=3} |
| Indexing: yes | | Indexing: no | | Key lookup |
| Duplicates: yes | | Duplicates: no | | Keys are unique |
+------------------+ +-------------------+ +---------------------+
5. Useful nuances
When to use which collection?
List — when element order matters, duplicates are needed, and you need index-based access (for example, a task list, message history).
Set — when you only need unique elements and order doesn’t matter (for example, the set of unique users).
Map — when you need to associate keys and values (for example, a phone book where the name is the key and the phone number is the value).
Real-world analogies
List — a cafeteria queue: first in — first served; you can get in line multiple times (duplicates).
Set — a guest list for a party: each guest appears only once (uniqueness).
Map — an address book: each name has its own phone number.
Quick cheat sheet: collections vs arrays
| Array (int[]) | Collection (List<Integer>) | |
|---|---|---|
| Size | Fixed | Dynamic |
| Adding an element | Cumbersome | Easy: add() |
| Removing an element | Cumbersome | Easy: remove() |
| Search by value | Manual iteration | Methods: contains(), etc. |
| Sorting | Via Arrays.sort() | Via Collections.sort(), collection methods |
| Uniqueness support | No | Via Set |
| Key–value pairs | No | Via Map |
6. Collections and OOP
Collections are objects that implement certain interfaces (List, Set, Map). This means you can:
- Store any objects in collections, including instances of your own classes.
- Create collections of collections (for example, a list of lists).
- Use collections as method parameters and return values.
- Extend collection functionality using inheritance and composition.
Example: a collection of objects of your class
import java.util.ArrayList;
import java.util.List;
class Student {
String name;
int age;
// Constructor, getters/setters, etc.
}
public class Main {
public static void main(String[] args) {
List<Student> group = new ArrayList<>();
group.add(new Student("Ivan", 20));
group.add(new Student("Maria", 21));
// and so on...
}
}
7. Common mistakes when working with collections
Error #1: Using collections without a type (raw types).
If you write ArrayList list = new ArrayList(), then when adding any object (for example, mixing strings and numbers) the compiler won’t complain, but later, when you try to retrieve an element and cast it to the needed type, you can get a runtime error (ClassCastException). Always use generics: ArrayList<String> list = new ArrayList<>().
Error #2: Forgot to import the required class.
If you see “cannot find symbol,” check that you have a line at the top of the file like import java.util.ArrayList; or the appropriate import for your collection.
Error #3: Confusing collections and arrays.
A collection is not an array! A collection has no length field — use the size() method instead. An array has no add() method; a collection has no [] operator for index access (only lists via get(index)).
Error #4: Expecting that element order is always preserved.
If you use a Set or a Map, element order is not guaranteed (unless you use special implementations like LinkedHashSet or TreeMap). For ordered data, use a List or the appropriate collections.
Error #5: Using primitive types in collections.
Collections can store only objects, not primitives. You cannot create a List<int>, only a List<Integer>. Don’t forget about wrapper classes!
GO TO FULL VERSION