Collections

Java Collections Framework Tutorial 1. What is the Collections Framework?

The Collections Framework provides a unified architecture for representing and manipulating collections. This framework includes:

Core Collection Interfaces

List

A List is an ordered collection of elements that allows duplicate values. It can grow or shrink dynamically, and elements can be inserted or accessed by their position in the list.

List Implementations:

Creating a List:

List<String> arrayList = new ArrayList<>();
List<String> linkedList = new LinkedList<>();

Adding Elements:

arrayList.add("Apple");
arrayList.add("Banana");
arrayList.add(1, "Cherry"); // Inserts at position 1

Accessing Elements

String fruit = arrayList.get(1); // Banana

Removing Elements

arrayList.remove(1); // Removes "Banana"
arrayList.remove("Apple");

Iterating Over a List

for(String item : arrayList) {
System.out.println(item);
}

Checking Size and Contents

int size = arrayList.size();
boolean containsApple = arrayList.contains("Apple");

Bulk Operations

List<String> anotherList = Arrays.asList("Grape", "Mango");
arrayList.addAll(anotherList); // Appends all elements from anotherList

Replace Element

arrayList.set(1, "Berry"); // Replaces the element at index 1

Sublist

List<String> subList = arrayList.subList(1, 3); // Includes the starting index, excludes the end index

Streams with Lists

// Using streams to filter and print items
arrayList.stream()
.filter(item -> item.startsWith("A"))
.forEach(System.out::println);

Common Pitfalls

Set

A Set is a collection that does not allow duplicate elements. It models the mathematical set abstraction and is part of the Java Collections Framework.

Set Implementations:

Creating a Set

Set<String> hashSet = new HashSet<>();
Set<String> linkedHashSet = new LinkedHashSet<>();
Set<String> treeSet = new TreeSet<>();

Adding Elements

hashSet.add("Apple");
hashSet.add("Banana");
hashSet.add("Apple"); // Duplicate, will not be added

Removing Elements

hashSet.remove("Apple");

contains an Element:

boolean hasApple = hashSet.contains("Apple");

Iterat3

for(String item : hashSet) 
   System.out.println(item);

Size

int size = hashSet.size();

Union

Set<String> anotherSet = new HashSet<>(Arrays.asList("Grape", "Mango"));
Set<String> union = new HashSet<>(hashSet);
union.addAll(anotherSet);

Intersection

Set<String> intersection = new HashSet<>(hashSet);
intersection.retainAll(anotherSet);

Difference

Set<String> difference = new HashSet<>(hashSet);
difference.removeAll(anotherSet);

TreeSet

TreeSet<Integer> numbers = new TreeSet<>();
numbers.add(10);
numbers.add(20);
numbers.add(30);

Integer highest = numbers.last();
Integer lowest = numbers.first();

Streams with Sets

hashSet.stream()
.filter(item -> item.startsWith("A"))
.forEach(System.out::println);

Common Pitfalls

Queue

A Queue is a collection designed to hold elements until they are processed or until their time to be processed arrives. Elements are typically processed in a first-in-first-out (FIFO) order, though exceptions like priority queues exist.

Queue Implementations:

Creating a Queue

Queue<String> linkedListQueue = new LinkedList<>();
Queue<String> priorityQueue = new PriorityQueue<>();
Queue<String> arrayDequeQueue = new ArrayDeque<>();

Adding Elements:

linkedListQueue.offer("Apple");
linkedListQueue.offer("Banana");

Retrieving and Removing Elements

String head = linkedListQueue.poll(); // Retrieves and removes head; returns null if empty
String peekHead = linkedListQueue.peek(); // Retrieves but doesn't remove head; returns null if empty

Size and contains

int size = linkedListQueue.size();
boolean containsApple = linkedListQueue.contains("Apple");

PriorityQueue

With a PriorityQueue, elements are assigned priorities. When you retrieve an element, the element with the highest priority is returned. If multiple elements have the same priority, they are processed according to their order in the queue.

Example with integers (their natural order is used):

PriorityQueue<Integer> numbers = new PriorityQueue<>();
numbers.offer(10);
numbers.offer(5);
System.out.println(numbers.poll()); // Outputs 5 because it's smaller

Example with custom objects and comparators:

class Person {
    String name;
    int age;
    public Person(String name, int age) {
        this.name = name;
        this.age = age;
  }
}

// Create a PriorityQueue where persons are ordered by their age
PriorityQueue<Person> people = new PriorityQueue<>(Comparator.comparingInt(person -> person.age));
people.offer(new Person("Alice", 30));
people.offer(new Person("Bob", 25));
System.out.println(people.poll().name); // Outputs Bob as he is younger

Best Practices

Map

A Map represents a collection of key-value pairs where each key is mapped to exactly one value. The keys are unique, but values can be duplicated.

Map Implementations:

Creating a Map

Map<String, Integer> hashMap = new HashMap<>();
Map<String, Integer> linkedHashMap = new LinkedHashMap<>();
Map<String, Integer> treeMap = new TreeMap<>();

Putting Key-Value Pairs

hashMap.put("Apple", 100);
hashMap.put("Banana", 60);

Getting Values

int applePrice = hashMap.get("Apple"); // Returns 100

Removing Key-Value Pairs

hashMap.remove("Apple");

Checking for Keys/Values:

boolean hasApple = hashMap.containsKey("Apple");
boolean hasPrice100 = hashMap.containsValue(100);

Iterating

for (Map.Entry<String, Integer> entry : hashMap.entrySet()) {
  System.out.println(entry.getKey() + ": " + entry.getValue());
}

Bulk Operations

Map<String, Integer> anotherMap = new HashMap<>();
anotherMap.putAll(hashMap); // Puts all mappings from hashMap into anotherMap

Default Methods (Java 8 and Beyond):

hashMap.getOrDefault("Cherry", 0); // Returns 0 if "Cherry" isn't in the map

hashMap.putIfAbsent("Apple", 80); // Puts the value if "Apple" isn't already mapped

hashMap.replace("Banana", 70); // Replaces the existing value for "Banana"

Streams with Maps

Filter a map to create another one with prices greater than 80:

Map<String, Integer> expensiveFruits = hashMap.entrySet()
.stream()
.filter(entry -> entry.getValue() > 80)
.collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue));

Best Practices:

Exercises

List

Set

Queue

Map

Solutions

List

Basic Operations:

Intermediate Operations:

Advanced Operations:

Set

Basic Operations:

Set<String> animals = new HashSet<>();
animals.addAll(Arrays.asList("Lion", "Tiger", "Panther", "Cheetah", "Leopard"));
boolean containsPanther = animals.contains("Panther");
System.out.println(containsPanther);
animals.remove("Leopard");
animals.add("Tiger"); // Nothing will happen since "Tiger" is already in the set.

Intermediate Operations:

TreeSet<Integer> numbers = new TreeSet<>();
numbers.addAll(Arrays.asList(15, 5, 29, 5, 42, 19));
System.out.println("First element: " + numbers.first());
System.out.println("Last element: " + numbers.last());
LinkedHashSet<String> steps = new LinkedHashSet<>();
steps.addAll(Arrays.asList("Step1", "Step2", "Step3", "Step4"));
steps.remove("Step2");
System.out.println(steps);

Advanced Operations:

HashSet<String> set1 = new HashSet<>(Arrays.asList("a", "b", "c", "d"));
HashSet<String> set2 = new HashSet<>(Arrays.asList("c", "d", "e", "f"));
// Union
HashSet<String> union = new HashSet<>(set1);
union.addAll(set2);
System.out.println("Union: " + union);
// Intersection
HashSet<String> intersection = new HashSet<>(set1);
intersection.retainAll(set2);
System.out.println("Intersection: " + intersection);
TreeSet<Integer> treeSetNumbers = new TreeSet<>(Arrays.asList(5, 1, 7, 6, 8, 2));
System.out.println("Higher than 5: " + treeSetNumbers.higher(5));
System.out.println("Lower than 5: " + treeSetNumbers.lower(5));

Queue

Basic Operations:

Intermediate Operations:

Advanced Operations:

Map

Basic Operations:

Advanced Operations: