Collection helper methods
For typical collection tasks you do not need to write loops: find the maximum, reverse a list, count repeats. Ready-made static methods are gathered in the Collections class — with an "s" at the end, unlike the Collection interface.
Maximum, minimum and counting
Collections.max() and Collections.min() find the largest and smallest element, and Collections.frequency() counts how many times a value occurs:
void main() {
List<Integer> grades = List.of(4, 5, 3, 5, 4, 5);
IO.println(Collections.max(grades));
IO.println(Collections.min(grades));
IO.println(Collections.frequency(grades, 5));
}Output:
5
3
3max() and min() also accept a comparator as the second argument — to find the longest word, for example.
Rearranging
reverse() reverses a list, swap() swaps two elements, and shuffle() mixes them in random order. All of them change the list itself:
void main() {
List<String> steps = new ArrayList<>(List.of("one", "two", "three"));
Collections.reverse(steps);
IO.println(steps);
Collections.swap(steps, 0, 2);
IO.println(steps);
}Output:
[three, two, one]
[one, two, three]The result of shuffle() is different on every run — that is how you shuffle a deck of cards or quiz questions.
Filling
Collections.nCopies() creates a list of identical elements, and Collections.addAll() adds several values to a collection at once:
void main() {
List<String> seats = new ArrayList<>(Collections.nCopies(4, "free"));
seats.set(1, "taken");
IO.println(seats);
Set<String> colors = new TreeSet<>();
Collections.addAll(colors, "blue", "white", "blue");
IO.println(colors);
}Output:
[free, taken, free, free]
[blue, white]A copy or a view
List.copyOf() makes an unmodifiable copy: later changes to the original do not affect it. Collections.unmodifiableList() returns a view — a read-only "window" onto the same list. You cannot make changes through the window, but changes to the original are visible in it:
void main() {
List<String> team = new ArrayList<>(List.of("Anna"));
List<String> copy = List.copyOf(team);
List<String> view = Collections.unmodifiableList(team);
team.add("Oleg");
IO.println(copy);
IO.println(view);
}Output:
[Anna]
[Anna, Oleg]A view suits a getter that must hand out up-to-date data without the right to change it.
Empty collections
A method that has nothing to return should return an empty collection, not null — then the calling code needs no extra checks. For this there is List.of() without arguments, as well as Map.of() and Set.of():
List<String> findByTag(String tag) {
if (tag.equals("java")) {
return List.of("Lesson 1", "Lesson 2");
}
return List.of();
}
void main() {
IO.println(findByTag("java").size());
IO.println(findByTag("php").size());
}Output:
2
0Common mistake
Arrays.asList() turns an array into a list, but that list has a fixed size: you can replace elements, but you cannot add them:
void main() {
String[] array = { "a", "b" };
List<String> list = Arrays.asList(array);
list.set(0, "z");
IO.println(list);
list.add("c");
}Output:
[z, b]
Exception in thread "main" java.lang.UnsupportedOperationExceptionIf the list is going to grow, create a full one: new ArrayList<>(Arrays.asList(array)).