# Collections: Java
## List Interface
The List interface is a child of Collection Interface. The List interface is found in `java.util` package and inherits the Collection interface.
### ArrayList
An ArrayList in Java is implemented as a resizable array, also known as a dynamic array. It provides an interface to work with a dynamically sized list of elements, allowing for efficient insertion, deletion, and random access.
```java!
import java.util.ArrayList;
import java.util.List;
public class ListObjectUsingArrayList {
public static void main(String[] args) {
// Initializing ArrayList with a specific initial capacity
int n = 10;
List<String> arrayList = new ArrayList<>(n);
// Adding elements
arrayList.add("Element 1");
arrayList.add("Element 2");
arrayList.add("Element 3");
// Accessing elements
String firstElement = arrayList.get(0);
System.out.println("First Element: " + firstElement);
// Updating elements
arrayList.set(1, "Updated Element 2");
// Removing first occurrence of given element
arrayList.remove("Element 1");
System.out.println(arrayList);
// Remove element at index 1
arrayList.remove(1);
System.out.println(arrayList);
// Checking if an element exists
boolean containsElement = arrayList.contains("Element 2");
System.out.println("Contains Element 2: " + containsElement);
// Getting the size
int size = arrayList.size();
System.out.println("Size of ArrayList: " + size);
// Iterating through elements
for (String element : arrayList) {
System.out.println(element);
}
// Checking if the ArrayList is empty
boolean isEmpty = arrayList.isEmpty();
System.out.println("Is ArrayList Empty: " + isEmpty);
// Clearing all elements
arrayList.clear();
System.out.println("ArrayList after clearing: " + arrayList);
}
}
```
### Vector
A vector provides us with dynamic arrays in Java. Though, it may be slower than standard arrays but can be helpful in programs where lots of manipulation in the array is needed.
Let’s see how to create a List object using Vector class:
```java!
List<Integer> vector = new Vector<>(n);
```
### Stack
Stack is a class that is implemented in the collection framework and extends the vector class models and implements the Stack data structure. The class is based on the basic principle of last-in-first-out.
Let’s see how to create a List object using Stack class:
```java!
List<Integer> stackObject = new Stack<Integer>();
```
### LinkedList
LinkedList is a class that is implemented in the collection framework which inherently implements the linked list data structure.
It is a linear data structure where the elements are not stored in contiguous locations and every element is a separate object with a data part and address part.
Let’s see how to create a List object using LinkedList class:
```java!
List<Integer> ll = new LinkedList<Integer>();
```
## Set Interface
The Set interface extends the Collection interface. It represents the unordered set of elements which doesn’t allow us to store the duplicate items.
### HashSet
HashSet is one of the widely used classes which implements the Set interface.
```java!
import java.util.HashSet;
import java.util.Set;
public class HashSetOperations {
public static void main(String[] args) {
// Adding elements
Set<String> hs = new HashSet<>();
hs.add("B");
hs.add("B");
hs.add("C");
hs.add("A");
// Printing the elements inside the Set object
System.out.println("HashSet after adding elements: " + hs);
// Accessing elements
System.out.println("Set is " + hs);
String check = "D";
System.out.println("Contains " + check + ": " + hs.contains(check));
// Removing elements
System.out.println("Initial HashSet: " + hs);
hs.remove("B");
System.out.println("After removing element 'B': " + hs);
// Iterating through the Set
System.out.print("Set elements: ");
for (String value : hs) {
System.out.print(value + ", ");
}
System.out.println();
}
}
```
### LinkedHashSet
LinkedHashSet class which is implemented in the collections framework is an ordered version of HashSet that maintains a doubly-linked List across all elements.
```java!
// Java program to demonstrate the
// creation of Set object using
// the LinkedHashset class
import java.util.*;
class LinkedHashSetClass {
public static void main(String[] args)
{
Set<String> lh = new LinkedHashSet<String>();
// Adding elements into the LinkedHashSet
// using add()
lh.add("India");
lh.add("Australia");
lh.add("South Africa");
// Adding the duplicate
// element
lh.add("India");
// Displaying the LinkedHashSet
System.out.println(lh);
// Removing items from LinkedHashSet
// using remove()
lh.remove("Australia");
System.out.println("Set after removing "
+ "Australia:" + lh);
// Iterating over linked hash set items
System.out.println("Iterating over set:");
Iterator<String> i = lh.iterator();
while (i.hasNext())
System.out.println(i.next());
}
}
```
## Sorted Set Interface
The SortedSet interface present in java.util package extends the Set interface present in the collection framework. It is an interface that implements the mathematical set.
### TreeSet
TreeSet class which is implemented in the collections framework and implementation of the SortedSet Interface and SortedSet extends Set Interface.
Let’s see how to create a Set object using TreeSet class:
```java!
Set<String> ts = new TreeSet<String>();
```
## Map Interface
In Java, Map Interface is present in java.util package represents a mapping between a key and a value. Java Map interface is not a subtype of the Collection interface. Therefore it behaves a bit differently from the rest of the collection types.
### HashMap
HashMap provides the basic implementation of the Map interface of Java. It stores the data in (Key, Value) pairs.
To access a value one must know its key.
```java!
// Java Program to illustrate the Hashmap Class
// Importing required classes
import java.util.*;
// Main class
public class MapObjectUsingHashMap {
// Main driver method
public static void main(String[] args)
{
// Creating an empty HashMap
Map<String, Integer> map = new HashMap<>();
// Inserting entries in the Map
// using put() method
map.put("vishal", 10);
map.put("sachin", 30);
map.put("vaibhav", 20);
// Iterating over Map
for (Map.Entry<String, Integer> e : map.entrySet())
// Printing key-value pairs
System.out.println(e.getKey() + " "
+ e.getValue());
}
}
```
### LinkedHashMap
LinkedHashMap is just like HashMap with the additional feature of maintaining an order of elements inserted into it.
Let’s see how to create a Map object using LinkedHashMap class:
```java!
Map<String, Integer> map = new LinkedHashMap<>();
```
### TreeMap
The map is sorted according to the natural ordering of its keys, or by a Comparator provided at map creation time, depending on which constructor is used. This proves to be an efficient way of sorting and storing the key-value pairs.
Let’s see how to create a Map object using TreeMap class:
```java!
Map<String, Integer> map = new TreeMap<>();
```
## Queue Interface
The Queue interface is present in java.util package and extends the Collection interface is used to hold the elements about to be processed in FIFO(First In First Out) order.
### LinkedList
```java!
import java.util.LinkedList;
import java.util.Queue;
public class QueueExample {
public static void main(String[] args) {
Queue<String> queue = new LinkedList<>();
// add elements to the queue
queue.add("apple");
queue.add("banana");
queue.add("cherry");
// print the queue
System.out.println("Queue: " + queue);
// remove the element at the front of the queue
String front = queue.remove();
System.out.println("Removed element: " + front);
// print the updated queue
System.out.println("Queue after removal: " + queue);
// add another element to the queue
queue.add("date");
// peek at the element at the front of the queue
String peeked = queue.peek();
System.out.println("Peeked element: " + peeked);
// print the updated queue
System.out.println("Queue after peek: " + queue);
}
}
```
### PriorityQueue
```java!
import java.util.*;
public class PriorityQueueOperations {
public static void main(String[] args) {
// Creating a PriorityQueue
Queue<String> pq = new PriorityQueue<>();
// Adding Elements
pq.add("Geeks");
pq.add("For");
pq.add("Geeks");
// Printing the PriorityQueue
System.out.println("PriorityQueue after adding elements: " + pq);
// Removing Elements
System.out.println("Initial Queue: " + pq);
pq.remove("Geeks");
System.out.println("After Remove: " + pq);
System.out.println("Poll Method: " + pq.poll()); // Removes and retrieves the head
System.out.println("Final Queue: " + pq);
// Iterating through the Queue using Iterator
System.out.print("Iterating using Iterator: ");
Iterator<String> iterator = pq.iterator();
while (iterator.hasNext()) {
System.out.print(iterator.next() + " ");
}
System.out.println();
// Other operations:
// Peek: Retrieves, but does not remove, the head of this queue
System.out.println("Peek: " + pq.peek());
// Size: Returns the number of elements in the queue
System.out.println("Size of Queue: " + pq.size());
// Contains: Checks if a specific element is present in the queue
System.out.println("Contains 'For': " + pq.contains("For"));
// Clear: Removes all elements from the queue
pq.clear();
System.out.println("Queue after clearing: " + pq);
}
}
```
## Deque Interface
Deque interface present in java.util package is a subtype of the queue interface. The Deque is related to the double-ended queue that supports the addition or removal of elements from either end of the data structure. It can either be used as a queue(first-in-first-out/FIFO) or as a stack(last-in-first-out/LIFO). Deque is the acronym for double-ended queue.
### LinkedList
```java!
// Java program to demonstrate the working
// of a Deque in Java
import java.util.*;
public class DequeExample {
public static void main(String[] args)
{
Deque<String> deque
= new LinkedList<String>();
// We can add elements to the queue
// in various ways
// Add at the last
deque.add("Element 1 (Tail)");
// Add at the first
deque.addFirst("Element 2 (Head)");
// Add at the last
deque.addLast("Element 3 (Tail)");
// Add at the first
deque.push("Element 4 (Head)");
// Add at the last
deque.offer("Element 5 (Tail)");
// Add at the first
deque.offerFirst("Element 6 (Head)");
System.out.println(deque + "\n");
// We can remove the first element
// or the last element.
deque.removeFirst();
deque.removeLast();
System.out.println("Deque after removing "
+ "first and last: "
+ deque);
}
}
```
### ArrayDeque
```java!
import java.util.ArrayDeque;
import java.util.Deque;
public class ArrayDequeExample {
public static void main(String[] args) {
Deque<String> deque = new ArrayDeque<>();
// Adding elements to the deque in various ways
deque.add("Element 1 (Tail)");
System.out.println(deque);
deque.addFirst("Element 2 (Head)");
System.out.println(deque);
deque.addLast("Element 3 (Tail)");
System.out.println(deque);
deque.push("Element 4 (Head)");
System.out.println(deque);
deque.offer("Element 5 (Tail)");
System.out.println(deque);
deque.offerFirst("Element 6 (Head)");
System.out.println(deque);
// Removing elements from the deque
deque.removeFirst();
deque.removeLast();
System.out.println("Deque after removing first and last: " + deque);
// Other operations on ArrayDeque
System.out.println("Peek First: " + deque.peekFirst());
System.out.println("Peek Last: " + deque.peekLast());
System.out.println("Poll First: " + deque.pollFirst());
System.out.println("Poll Last: " + deque.pollLast());
System.out.println("Size of Deque: " + deque.size());
System.out.println("Contains 'Element 3 (Tail)': " + deque.contains("Element 3 (Tail)"));
// Clearing all elements
deque.clear();
System.out.println("Deque after clearing: " + deque);
}
}
```
## Comparables
The Comparable interface in Java is essential for defining a natural ordering for a class. By implementing Comparable, a class provides a standardized way to compare instances of that class. This natural ordering is particularly useful for sorting elements in collections like TreeSet or when utilizing sorting algorithms such as Collections.sort().
The Comparable interface contains a single method:
```java!
int compareTo(T other)
```
Here, T represents the type of objects being compared. The `compareTo` method returns a negative integer, zero, or a positive integer based on whether the current object is less than, equal to, or greater than the object being compared.
For example, consider a Person class that implements the Comparable interface to define a natural ordering based on age:
```java
import java.util.*;
class Person implements Comparable<Person> {
String name;
int age;
public Person(String name, int age) {
this.name = name;
this.age = age;
}
@Override
public int compareTo(Person other) {
return Integer.compare(this.age, other.age);
}
}
```
## Comparators
In Java, the Comparator interface provides a means to define custom ordering for objects in collections. It is particularly useful when sorting objects in a way that deviates from their natural order or when working with classes that don't implement Comparable.
Here's a simple example of how you might use a Comparator to sort a list of Person objects based on their ages:
```java
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
class Person {
String name;
int age;
public Person(String name, int age) {
this.name = name;
this.age = age;
}
}
class AgeComparator implements Comparator<Person> {
@Override
public int compare(Person person1, Person person2) {
return Integer.compare(person1.age, person2.age);
}
}
public class ComparatorExample {
public static void main(String[] args) {
List<Person> people = new ArrayList<>();
people.add(new Person("Alice", 28));
people.add(new Person("Bob", 22));
people.add(new Person("Charlie", 25));
// Sort the list using the AgeComparator
Collections.sort(people, new AgeComparator());
// Iterate the List of people and check if it is now sorted on the basis of age or not.
for (Person person : people) {
System.out.println(person.name + " - " + person.age);
}
}
}
```