Java Utility Package - Complete Guide
Master Java utility package (java.util): Learn Collections Framework, Date-Time API, utility classes, and essential tools for effective Java programming with practical examples.
Introduction to java.util
The java.util package is one of Java's most important packages, providing:
- Collections Framework — Data structures like Lists, Sets, Maps
- Utility Classes — Arrays, Collections, Objects
- Date/Time — Date, Calendar (largely replaced by
java.time) - Random Number Generation — Random, ThreadLocalRandom
- Input/Output — Scanner, StringTokenizer
- Event Model — EventObject, EventListener
What are Utility Classes?
Utility classes in Java provide static helper methods for common operations. They:
- Cannot be instantiated (private constructor)
- Contain only static methods
- Are
finalto prevent inheritance - Provide reusable functionality across your application
Common Utility Classes in java.util
| Utility Class | Purpose |
|---|---|
| Collections | Operations on collections (sort, search, synchronize) |
| Arrays | Operations on arrays (sort, fill, copy, stream) |
| Objects | Null-safe object operations |
| Scanner | Parsing primitive types and tokens from input |
| Random | Generating pseudo-random numbers |
| UUID | Generating universally unique identifiers |
| Properties | Managing key-value configuration |
| Optional | Representing optional values without null |
Collections Framework
The Collections Framework provides a unified architecture for storing and manipulating groups of objects.
Core Interfaces Hierarchy
Iterable (interface)
│
└── Collection (interface)
│
├── List (interface) - Ordered, allows duplicates
│ ├── ArrayList
│ ├── LinkedList
│ └── Vector
│
├── Set (interface) - No duplicates, unordered
│ ├── HashSet
│ ├── LinkedHashSet
│ └── TreeSet
│
└── Queue (interface) - FIFO order
├── PriorityQueue
└── Deque (interface)
└── ArrayDeque
Map (interface) - Key-value pairs
├── HashMap
├── LinkedHashMap
├── TreeMap
└── Hashtable
Lists: ArrayList, LinkedList, Vector
ArrayList — Dynamic Array
Best for: Random access, frequent reads, fewer insertions/deletions
import java.util.*;
public class ArrayListDemo {
public static void main(String[] args) {
// Create ArrayList
ArrayList<String> fruits = new ArrayList<>();
// Add elements
fruits.add("Apple");
fruits.add("Banana");
fruits.add("Orange");
fruits.add("Mango");
fruits.add(2, "Grape"); // Insert at index 2
System.out.println("Fruits: " + fruits);
// Access elements
String first = fruits.get(0);
System.out.println("First fruit: " + first);
// Modify elements
fruits.set(1, "Blueberry");
System.out.println("After modification: " + fruits);
// Remove elements
fruits.remove("Orange"); // By object
fruits.remove(2); // By index
System.out.println("After removal: " + fruits);
// Check existence
boolean hasApple = fruits.contains("Apple");
System.out.println("Contains Apple? " + hasApple);
// Get index
int index = fruits.indexOf("Mango");
System.out.println("Mango at index: " + index);
// Iteration methods
System.out.println("\n--- For loop ---");
for (int i = 0; i < fruits.size(); i++) {
System.out.println(fruits.get(i));
}
System.out.println("\n--- Enhanced for loop ---");
for (String fruit : fruits) {
System.out.println(fruit);
}
System.out.println("\n--- Iterator ---");
Iterator<String> iterator = fruits.iterator();
while (iterator.hasNext()) {
System.out.println(iterator.next());
}
System.out.println("\n--- forEach with lambda (Java 8+) ---");
fruits.forEach(fruit -> System.out.println(fruit));
// Bulk operations
ArrayList<String> moreFruits = new ArrayList<>();
moreFruits.add("Kiwi");
moreFruits.add("Pear");
fruits.addAll(moreFruits);
System.out.println("After addAll: " + fruits);
// Convert to array
String[] fruitArray = fruits.toArray(new String[0]);
System.out.println("Array length: " + fruitArray.length);
// Clear all
fruits.clear();
System.out.println("Is empty? " + fruits.isEmpty());
// Performance: ensure capacity
ArrayList<Integer> numbers = new ArrayList<>(100); // Initial capacity
numbers.ensureCapacity(1000); // Ensure capacity for 1000 elements
}
}
LinkedList — Doubly Linked List
Best for: Frequent insertions/deletions at ends or middle
import java.util.*;
public class LinkedListDemo {
public static void main(String[] args) {
LinkedList<String> linkedList = new LinkedList<>();
// Add elements
linkedList.add("First");
linkedList.add("Second");
linkedList.add("Third");
// Add at specific positions
linkedList.addFirst("Zero"); // Add at beginning
linkedList.addLast("Fourth"); // Add at end
linkedList.add(2, "OnePointFive"); // Add at index
System.out.println("LinkedList: " + linkedList);
// Queue operations
linkedList.offer("Fifth"); // Add to end (queue)
linkedList.offerFirst("Negative"); // Add to front
linkedList.offerLast("Sixth"); // Add to end
// Stack operations
linkedList.push("PushMe"); // Add to front
// Retrieve elements
String first = linkedList.getFirst();
String last = linkedList.getLast();
String element = linkedList.get(3);
System.out.println("First: " + first + ", Last: " + last);
// Remove elements
linkedList.removeFirst();
linkedList.removeLast();
linkedList.remove(2);
linkedList.remove("Second");
// Queue removal
String polled = linkedList.poll(); // Remove and return first
String polledFirst = linkedList.pollFirst();
String polledLast = linkedList.pollLast();
// Stack removal
String popped = linkedList.pop(); // Remove and return first
System.out.println("After removals: " + linkedList);
// Peek without removing
String peek = linkedList.peek();
String peekFirst = linkedList.peekFirst();
String peekLast = linkedList.peekLast();
// Use as Queue (FIFO)
LinkedList<Integer> queue = new LinkedList<>();
queue.offer(1); // Enqueue
queue.offer(2);
queue.offer(3);
System.out.println("Queue poll: " + queue.poll()); // 1
// Use as Stack (LIFO)
LinkedList<Integer> stack = new LinkedList<>();
stack.push(1); // Push
stack.push(2);
stack.push(3);
System.out.println("Stack pop: " + stack.pop()); // 3
}
}
Vector — Legacy Thread-Safe List
import java.util.*;
public class VectorDemo {
public static void main(String[] args) {
// Vector is synchronized (thread-safe but slower)
Vector<String> vector = new Vector<>();
// Add elements
vector.add("Element 1");
vector.add("Element 2");
vector.addElement("Element 3"); // Legacy method
// Vector-specific methods
System.out.println("Capacity: " + vector.capacity());
System.out.println("Size: " + vector.size());
// Enumeration (legacy iteration)
Enumeration<String> enumeration = vector.elements();
while (enumeration.hasMoreElements()) {
System.out.println(enumeration.nextElement());
}
// Trim capacity to size
vector.trimToSize();
System.out.println("Capacity after trim: " + vector.capacity());
// Set initial capacity and increment
Vector<Integer> customVector = new Vector<>(20, 5); // Initial 20, grow by 5
}
}
Performance Comparison
import java.util.*;
public class ListPerformanceComparison {
public static void main(String[] args) {
int size = 100000;
// ArrayList vs LinkedList performance
List<Integer> arrayList = new ArrayList<>();
List<Integer> linkedList = new LinkedList<>();
// 1. Add at end
long start = System.nanoTime();
for (int i = 0; i < size; i++) arrayList.add(i);
long arrayListAddTime = System.nanoTime() - start;
start = System.nanoTime();
for (int i = 0; i < size; i++) linkedList.add(i);
long linkedListAddTime = System.nanoTime() - start;
System.out.println("Add at end - ArrayList: " + arrayListAddTime/1e6 + "ms");
System.out.println("Add at end - LinkedList: " + linkedListAddTime/1e6 + "ms");
// 2. Add at beginning
start = System.nanoTime();
for (int i = 0; i < 1000; i++) arrayList.add(0, i);
long arrayListAddFirst = System.nanoTime() - start;
start = System.nanoTime();
for (int i = 0; i < 1000; i++) linkedList.add(0, i);
long linkedListAddFirst = System.nanoTime() - start;
System.out.println("\nAdd at beginning - ArrayList: " + arrayListAddFirst/1e6 + "ms");
System.out.println("Add at beginning - LinkedList: " + linkedListAddFirst/1e6 + "ms");
// 3. Random access
start = System.nanoTime();
for (int i = 0; i < 10000; i++) arrayList.get(i);
long arrayListGet = System.nanoTime() - start;
start = System.nanoTime();
for (int i = 0; i < 10000; i++) linkedList.get(i);
long linkedListGet = System.nanoTime() - start;
System.out.println("\nRandom access - ArrayList: " + arrayListGet/1e6 + "ms");
System.out.println("Random access - LinkedList: " + linkedListGet/1e6 + "ms");
// When to use each:
// ArrayList: Random access, iteration, adding/removing at end
// LinkedList: Adding/removing at beginning or middle, implementing queues/stacks
}
}
Sets: HashSet, TreeSet, LinkedHashSet
HashSet — Unordered, No Duplicates
import java.util.*;
import java.util.Objects;
public class HashSetDemo {
public static void main(String[] args) {
// Create HashSet
HashSet<String> set = new HashSet<>();
// Add elements
set.add("Apple");
set.add("Banana");
set.add("Orange");
set.add("Apple"); // Duplicate - will not be added
set.add("Mango");
System.out.println("HashSet: " + set); // Order not guaranteed
// Check size
System.out.println("Size: " + set.size());
// Check existence
System.out.println("Contains Banana? " + set.contains("Banana"));
// Remove element
set.remove("Orange");
// Iteration
System.out.println("\nIterating HashSet:");
for (String fruit : set) {
System.out.println(fruit);
}
// HashSet with custom objects (requires hashCode() and equals())
HashSet<Person> people = new HashSet<>();
people.add(new Person("Alice", 25));
people.add(new Person("Bob", 30));
people.add(new Person("Alice", 25)); // Duplicate - won't be added
System.out.println("People size: " + people.size());
// Bulk operations
HashSet<String> set1 = new HashSet<>(Arrays.asList("A", "B", "C"));
HashSet<String> set2 = new HashSet<>(Arrays.asList("B", "C", "D"));
// 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);
// Difference
HashSet<String> difference = new HashSet<>(set1);
difference.removeAll(set2);
System.out.println("Difference (set1 - set2): " + difference);
// Load factor and capacity
HashSet<Integer> customSet = new HashSet<>(100, 0.75f); // Initial capacity, load factor
}
}
class Person {
String name;
int age;
Person(String name, int age) {
this.name = name;
this.age = age;
}
@Override
public boolean equals(Object obj) {
if (this == obj) return true;
if (obj == null || getClass() != obj.getClass()) return false;
Person person = (Person) obj;
return age == person.age && Objects.equals(name, person.name);
}
@Override
public int hashCode() {
return Objects.hash(name, age);
}
}
TreeSet — Sorted Set
import java.util.*;
public class TreeSetDemo {
public static void main(String[] args) {
// Natural ordering (ascending)
TreeSet<Integer> numbers = new TreeSet<>();
numbers.add(5);
numbers.add(2);
numbers.add(8);
numbers.add(1);
numbers.add(9);
numbers.add(3);
System.out.println("TreeSet (sorted): " + numbers);
// Custom ordering with Comparator
TreeSet<String> reverseSet = new TreeSet<>(Comparator.reverseOrder());
reverseSet.add("Apple");
reverseSet.add("Banana");
reverseSet.add("Orange");
System.out.println("Reverse order: " + reverseSet);
// TreeSet methods
System.out.println("First: " + numbers.first());
System.out.println("Last: " + numbers.last());
System.out.println("Lower than 5: " + numbers.lower(5)); // Greatest element < 5
System.out.println("Higher than 5: " + numbers.higher(5)); // Smallest element > 5
System.out.println("Floor of 4: " + numbers.floor(4)); // Greatest element ≤ 4
System.out.println("Ceiling of 6: " + numbers.ceiling(6)); // Smallest element ≥ 6
// Subsets
SortedSet<Integer> subSet = numbers.subSet(2, 8); // 2 inclusive, 8 exclusive
System.out.println("Subset [2,8): " + subSet);
SortedSet<Integer> headSet = numbers.headSet(5); // Elements < 5
System.out.println("HeadSet (<5): " + headSet);
SortedSet<Integer> tailSet = numbers.tailSet(5); // Elements ≥ 5
System.out.println("TailSet (≥5): " + tailSet);
// Polling
System.out.println("Poll first: " + numbers.pollFirst());
System.out.println("Poll last: " + numbers.pollLast());
System.out.println("After polling: " + numbers);
// TreeSet with custom objects (must implement Comparable)
TreeSet<Student> students = new TreeSet<>();
students.add(new Student("Alice", 85));
students.add(new Student("Bob", 92));
students.add(new Student("Charlie", 78));
System.out.println("\nStudents sorted by grade:");
for (Student s : students) {
System.out.println(s);
}
}
}
class Student implements Comparable<Student> {
String name;
int grade;
Student(String name, int grade) {
this.name = name;
this.grade = grade;
}
@Override
public int compareTo(Student other) {
return Integer.compare(this.grade, other.grade);
}
@Override
public String toString() {
return name + ": " + grade;
}
}
LinkedHashSet — Maintains Insertion Order
import java.util.*;
public class LinkedHashSetDemo {
public static void main(String[] args) {
// Maintains insertion order
LinkedHashSet<String> linkedHashSet = new LinkedHashSet<>();
linkedHashSet.add("Third");
linkedHashSet.add("First");
linkedHashSet.add("Second");
linkedHashSet.add("Fourth");
System.out.println("LinkedHashSet (insertion order): " + linkedHashSet);
// Compare with HashSet
HashSet<String> hashSet = new HashSet<>(linkedHashSet);
System.out.println("HashSet (no order): " + hashSet);
// TreeSet (sorted order)
TreeSet<String> treeSet = new TreeSet<>(linkedHashSet);
System.out.println("TreeSet (sorted): " + treeSet);
// When to use LinkedHashSet: When you need unique elements AND insertion order
}
}
Maps: HashMap, TreeMap, LinkedHashMap
HashMap — Key-Value Pairs
import java.util.*;
public class HashMapDemo {
public static void main(String[] args) {
// Create HashMap
HashMap<String, Integer> ages = new HashMap<>();
// Put key-value pairs
ages.put("Alice", 25);
ages.put("Bob", 30);
ages.put("Charlie", 35);
ages.put("Alice", 26); // Overwrites previous value
System.out.println("HashMap: " + ages);
// Get values
Integer aliceAge = ages.get("Alice");
System.out.println("Alice's age: " + aliceAge);
// Get with default
Integer davidAge = ages.getOrDefault("David", 0);
System.out.println("David's age (default): " + davidAge);
// Check existence
System.out.println("Contains Bob? " + ages.containsKey("Bob"));
System.out.println("Contains age 30? " + ages.containsValue(30));
// Remove
ages.remove("Charlie");
System.out.println("After removal: " + ages);
// Iterate through entries
System.out.println("\nIterating through HashMap:");
for (Map.Entry<String, Integer> entry : ages.entrySet()) {
System.out.println(entry.getKey() + " -> " + entry.getValue());
}
// Iterate through keys
System.out.println("\nKeys: " + ages.keySet());
// Iterate through values
System.out.println("Values: " + ages.values());
// Compute methods
ages.putIfAbsent("Eve", 28);
ages.compute("Alice", (k, v) -> v + 1); // Increment age
ages.computeIfAbsent("Frank", k -> 40); // Add if absent
ages.computeIfPresent("Bob", (k, v) -> v + 5); // Modify if present
System.out.println("After compute operations: " + ages);
// Merge
ages.merge("Alice", 30, Integer::sum);
System.out.println("After merge: " + ages);
// Replace
ages.replace("Bob", 35);
ages.replace("Eve", 28, 29); // Replace only if current value is 28
// Get all entries
Set<Map.Entry<String, Integer>> entries = ages.entrySet();
// Create HashMap from another map
HashMap<String, Integer> copy = new HashMap<>(ages);
// Performance: initial capacity and load factor
HashMap<String, String> optimized = new HashMap<>(100, 0.9f);
}
}
TreeMap — Sorted Map
import java.util.*;
public class TreeMapDemo {
public static void main(String[] args) {
// Natural ordering
TreeMap<String, Integer> scores = new TreeMap<>();
scores.put("Charlie", 85);
scores.put("Alice", 95);
scores.put("Bob", 78);
scores.put("David", 92);
System.out.println("TreeMap (sorted by key): " + scores);
// Custom ordering (reverse alphabetical)
TreeMap<String, Integer> reverseMap = new TreeMap<>(Comparator.reverseOrder());
reverseMap.putAll(scores);
System.out.println("Reverse order: " + reverseMap);
// Navigation methods
System.out.println("First key: " + scores.firstKey());
System.out.println("Last key: " + scores.lastKey());
System.out.println("Lower key than C: " + scores.lowerKey("Charlie"));
System.out.println("Higher key than C: " + scores.higherKey("Charlie"));
System.out.println("Floor key (≤ B): " + scores.floorKey("Bob"));
System.out.println("Ceiling key (≥ B): " + scores.ceilingKey("Bob"));
// Submaps
SortedMap<String, Integer> subMap = scores.subMap("B", "D"); // B inclusive, D exclusive
System.out.println("Submap [B,D): " + subMap);
SortedMap<String, Integer> headMap = scores.headMap("C"); // Keys < C
System.out.println("HeadMap (<C): " + headMap);
SortedMap<String, Integer> tailMap = scores.tailMap("C"); // Keys ≥ C
System.out.println("TailMap (≥C): " + tailMap);
// Poll entries
Map.Entry<String, Integer> firstEntry = scores.pollFirstEntry();
Map.Entry<String, Integer> lastEntry = scores.pollLastEntry();
System.out.println("Removed first: " + firstEntry);
System.out.println("Removed last: " + lastEntry);
System.out.println("After polling: " + scores);
// TreeMap with custom comparator for values
TreeMap<Integer, String> ageToName = new TreeMap<>();
ageToName.put(25, "Alice");
ageToName.put(30, "Bob");
ageToName.put(22, "Charlie");
// Get nearest keys
System.out.println("Nearest age to 28: " + ageToName.ceilingKey(28));
System.out.println("Nearest age to 28 (lower): " + ageToName.floorKey(28));
}
}
LinkedHashMap — Maintains Insertion or Access Order
import java.util.*;
public class LinkedHashMapDemo {
public static void main(String[] args) {
// Insertion order (default)
LinkedHashMap<String, Integer> insertionOrder = new LinkedHashMap<>();
insertionOrder.put("Third", 3);
insertionOrder.put("First", 1);
insertionOrder.put("Second", 2);
System.out.println("Insertion order: " + insertionOrder);
// Access order (LRU cache)
LinkedHashMap<String, Integer> accessOrder = new LinkedHashMap<>(16, 0.75f, true);
accessOrder.put("A", 1);
accessOrder.put("B", 2);
accessOrder.put("C", 3);
System.out.println("Initial access order: " + accessOrder);
accessOrder.get("A");
System.out.println("After accessing A: " + accessOrder); // A moves to end
accessOrder.get("B");
System.out.println("After accessing B: " + accessOrder);
// Simple LRU Cache implementation
class LRUCache<K, V> extends LinkedHashMap<K, V> {
private final int maxSize;
LRUCache(int maxSize) {
super(16, 0.75f, true);
this.maxSize = maxSize;
}
@Override
protected boolean removeEldestEntry(Map.Entry<K, V> eldest) {
return size() > maxSize;
}
}
LRUCache<String, Integer> cache = new LRUCache<>(3);
cache.put("One", 1);
cache.put("Two", 2);
cache.put("Three", 3);
System.out.println("Cache: " + cache);
cache.put("Four", 4); // Removes eldest (One)
System.out.println("After adding Four: " + cache);
cache.get("Two");
cache.put("Five", 5); // Removes Three (least recently used)
System.out.println("Final cache: " + cache);
}
}
Queues and Deques
Queue Interface
import java.util.*;
public class QueueDemo {
public static void main(String[] args) {
// PriorityQueue - elements ordered by priority
PriorityQueue<Integer> pq = new PriorityQueue<>();
// Add elements
pq.add(5);
pq.add(2);
pq.add(8);
pq.add(1);
pq.add(9);
System.out.println("PriorityQueue: " + pq);
System.out.println("Head (peek): " + pq.peek());
// Remove elements (always smallest first)
System.out.println("Poll: " + pq.poll());
System.out.println("After poll: " + pq);
// PriorityQueue with custom comparator
PriorityQueue<Integer> maxHeap = new PriorityQueue<>(Comparator.reverseOrder());
maxHeap.addAll(Arrays.asList(5, 2, 8, 1, 9));
System.out.println("Max heap: " + maxHeap);
System.out.println("Max heap poll: " + maxHeap.poll());
// PriorityQueue with custom objects
PriorityQueue<Task> taskQueue = new PriorityQueue<>((t1, t2) ->
Integer.compare(t2.priority, t1.priority)); // Higher priority first
taskQueue.add(new Task("Low priority", 1));
taskQueue.add(new Task("High priority", 10));
taskQueue.add(new Task("Medium priority", 5));
System.out.println("\nProcessing tasks by priority:");
while (!taskQueue.isEmpty()) {
System.out.println(taskQueue.poll());
}
// ArrayDeque as Queue (FIFO)
Queue<String> arrayDequeQueue = new ArrayDeque<>();
arrayDequeQueue.offer("First");
arrayDequeQueue.offer("Second");
arrayDequeQueue.offer("Third");
System.out.println("\nArrayDeque as Queue:");
System.out.println("Poll: " + arrayDequeQueue.poll());
System.out.println("Poll: " + arrayDequeQueue.poll());
}
static class Task {
String name;
int priority;
Task(String name, int priority) {
this.name = name;
this.priority = priority;
}
@Override
public String toString() {
return name + " (priority: " + priority + ")";
}
}
}
Deque Interface — Double Ended Queue
import java.util.*;
public class DequeDemo {
public static void main(String[] args) {
// ArrayDeque - resizable array implementation
ArrayDeque<String> deque = new ArrayDeque<>();
// Add at both ends
deque.addFirst("First");
deque.addLast("Last");
deque.offerFirst("New First");
deque.offerLast("New Last");
System.out.println("Deque: " + deque);
// Peek at both ends
System.out.println("Peek First: " + deque.peekFirst());
System.out.println("Peek Last: " + deque.peekLast());
// Remove from both ends
System.out.println("Remove First: " + deque.removeFirst());
System.out.println("Remove Last: " + deque.removeLast());
System.out.println("After removals: " + deque);
// Stack operations (LIFO)
ArrayDeque<Integer> stack = new ArrayDeque<>();
stack.push(1); // push at front
stack.push(2);
stack.push(3);
System.out.println("\nStack (LIFO):");
System.out.println("Pop: " + stack.pop()); // 3
System.out.println("Pop: " + stack.pop()); // 2
// Queue operations (FIFO)
ArrayDeque<Integer> queue = new ArrayDeque<>();
queue.add(1); // add at end
queue.add(2);
queue.add(3);
System.out.println("\nQueue (FIFO):");
System.out.println("Remove: " + queue.remove()); // 1
System.out.println("Remove: " + queue.remove()); // 2
// Performance: ArrayList vs LinkedList vs ArrayDeque
int size = 100000;
// Test as Queue
Queue<Integer> arrayDequeQueue = new ArrayDeque<>();
Queue<Integer> linkedListQueue = new LinkedList<>();
long start = System.nanoTime();
for (int i = 0; i < size; i++) arrayDequeQueue.offer(i);
for (int i = 0; i < size; i++) arrayDequeQueue.poll();
long arrayDequeTime = System.nanoTime() - start;
start = System.nanoTime();
for (int i = 0; i < size; i++) linkedListQueue.offer(i);
for (int i = 0; i < size; i++) linkedListQueue.poll();
long linkedListTime = System.nanoTime() - start;
System.out.println("\nQueue Performance (offer + poll " + size + " items):");
System.out.println("ArrayDeque: " + arrayDequeTime/1e6 + "ms");
System.out.println("LinkedList: " + linkedListTime/1e6 + "ms");
// Use ArrayDeque when you need:
// - Fast add/remove at both ends
// - No null elements
// - Better performance than LinkedList
// - Stack or Queue implementation
}
}
Quick Reference Card
| Collection | Ordering | Duplicates | Nulls | Thread-Safe | Best For |
|---|---|---|---|---|---|
| ArrayList | Insertion | Yes | Yes | No | Random access, iteration |
| LinkedList | Insertion | Yes | Yes | No | Frequent insert/delete |
| HashSet | None | No | One null | No | Unique elements, fast lookup |
| TreeSet | Sorted | No | No | No | Sorted unique elements |
| LinkedHashSet | Insertion | No | One null | No | Unique + insertion order |
| HashMap | None | Keys:No, Values:Yes | Yes | No | Fast key-value lookup |
| TreeMap | Sorted by key | Keys:No | No | No | Sorted key-value pairs |
| LinkedHashMap | Insertion/Access | Keys:No | Yes | No | Ordered key-value pairs |
| PriorityQueue | Priority | Yes | No | No | Priority-based processing |
| ArrayDeque | FIFO/LIFO | Yes | No | No | Stack/Queue operations |
java.util.Collections
The Collections class provides static methods for operating on collections.
Basic Operations
import java.util.*;
public class CollectionsBasicDemo {
public static void main(String[] args) {
List<Integer> list = new ArrayList<>();
Collections.addAll(list, 5, 2, 8, 1, 9, 3, 7, 4, 6);
System.out.println("Original: " + list);
Collections.sort(list);
System.out.println("Sorted: " + list);
Collections.sort(list, Comparator.reverseOrder());
System.out.println("Reverse sorted: " + list);
Collections.sort(list);
int index = Collections.binarySearch(list, 5);
System.out.println("Index of 5: " + index);
Collections.reverse(list);
System.out.println("Reversed: " + list);
Collections.shuffle(list);
System.out.println("Shuffled: " + list);
Collections.rotate(list, 2);
System.out.println("Rotated by 2: " + list);
Collections.swap(list, 0, list.size() - 1);
System.out.println("Swapped first and last: " + list);
Collections.replaceAll(list, 5, 99);
System.out.println("Replaced 5 with 99: " + list);
Collections.fill(list, 0);
System.out.println("Filled with zeros: " + list);
}
}
Min, Max, Frequency
import java.util.*;
public class CollectionsStatsDemo {
public static void main(String[] args) {
List<Integer> numbers = Arrays.asList(5, 2, 8, 1, 9, 2, 7, 2, 6);
int min = Collections.min(numbers);
int max = Collections.max(numbers);
System.out.println("Min: " + min + ", Max: " + max);
List<String> words = Arrays.asList("apple", "banana", "cherry", "date");
String shortest = Collections.min(words, Comparator.comparingInt(String::length));
String longest = Collections.max(words, Comparator.comparingInt(String::length));
System.out.println("Shortest: " + shortest + ", Longest: " + longest);
int frequency = Collections.frequency(numbers, 2);
System.out.println("Frequency of 2: " + frequency);
List<Integer> list1 = Arrays.asList(1, 2, 3);
List<Integer> list2 = Arrays.asList(4, 5, 6);
List<Integer> list3 = Arrays.asList(3, 4, 5);
System.out.println("list1 & list2 disjoint? " + Collections.disjoint(list1, list2));
System.out.println("list1 & list3 disjoint? " + Collections.disjoint(list1, list3));
}
}
Creating Special Collections
import java.util.*;
public class CollectionsFactoryDemo {
public static void main(String[] args) {
List<String> modifiable = new ArrayList<>(Arrays.asList("a", "b", "c"));
List<String> unmodifiable = Collections.unmodifiableList(modifiable);
List<String> synced = Collections.synchronizedList(modifiable);
System.out.println("Empty list: " + Collections.emptyList());
System.out.println("Singleton: " + Collections.singletonList("only"));
System.out.println("Empty set: " + Collections.emptySet());
System.out.println("Empty map: " + Collections.emptyMap());
System.out.println("Checked list: " + Collections.checkedList(modifiable, String.class));
System.out.println("Unmodifiable copy: " + unmodifiable);
System.out.println("Synchronized list: " + synced);
}
}
Custom Sorting with Collections
import java.util.*;
class Person {
private final String name;
private final int age;
Person(String name, int age) {
this.name = name;
this.age = age;
}
String getName() { return name; }
int getAge() { return age; }
@Override
public String toString() {
return name + " (" + age + ")";
}
}
public class CollectionsSortingDemo {
public static void main(String[] args) {
List<Person> people = new ArrayList<>();
people.add(new Person("Charlie", 30));
people.add(new Person("Alice", 25));
people.add(new Person("Bob", 28));
Collections.sort(people, Comparator.comparing(Person::getName));
System.out.println("By name: " + people);
Collections.sort(people, Comparator.comparingInt(Person::getAge));
System.out.println("By age: " + people);
}
}
java.util.Arrays
The Arrays class contains static methods for array manipulation and comparison.
Basic Array Operations
import java.util.Arrays;
public class ArraysBasicDemo {
public static void main(String[] args) {
int[] nums = {5, 2, 8, 1, 9};
System.out.println("As list: " + Arrays.toString(nums));
Arrays.sort(nums);
System.out.println("Sorted: " + Arrays.toString(nums));
System.out.println("Binary search 8: " + Arrays.binarySearch(nums, 8));
int[] filled = new int[5];
Arrays.fill(filled, 7);
System.out.println("Filled: " + Arrays.toString(filled));
int[] copy = Arrays.copyOf(nums, nums.length);
System.out.println("Copy: " + Arrays.toString(copy));
System.out.println("Equals: " + Arrays.equals(nums, copy));
}
}
Multidimensional Arrays
import java.util.Arrays;
public class ArraysMultiDimDemo {
public static void main(String[] args) {
int[][] matrix = {{1, 2}, {3, 4}};
System.out.println("deepToString: " + Arrays.deepToString(matrix));
int[][] other = {{1, 2}, {3, 4}};
System.out.println("deepEquals: " + Arrays.deepEquals(matrix, other));
System.out.println("deepHashCode: " + Arrays.deepHashCode(matrix));
}
}
Parallel Sort
import java.util.Arrays;
public class ArraysParallelDemo {
public static void main(String[] args) {
int[] data = {9, 1, 8, 2, 7, 3, 6, 4, 5};
Arrays.parallelSort(data);
System.out.println("parallelSort: " + Arrays.toString(data));
}
}
Arrays and Streams
import java.util.Arrays;
public class ArraysStreamDemo {
public static void main(String[] args) {
int[] nums = {1, 2, 3, 4, 5};
int sum = Arrays.stream(nums).sum();
System.out.println("Sum via stream: " + sum);
Arrays.stream(nums).forEach(n -> System.out.print(n + " "));
System.out.println();
}
}
java.util.Objects
The Objects class offers null-safe helpers introduced in Java 7.
Null-Safe Object Utilities
import java.util.Objects;
public class ObjectsBasicDemo {
public static void main(String[] args) {
String a = "Java";
String b = null;
System.out.println("equals: " + Objects.equals(a, b));
System.out.println("hash: " + Objects.hash(a, "util"));
System.out.println("toString: " + Objects.toString(b, "default"));
System.out.println("isNull: " + Objects.isNull(b));
System.out.println("nonNull: " + Objects.nonNull(a));
System.out.println("compare: " + Objects.compare(10, 20, Integer::compareTo));
try {
Objects.requireNonNull(b, "value required");
} catch (NullPointerException ex) {
System.out.println("requireNonNull: " + ex.getMessage());
}
}
}
java.util.Scanner
Scanner breaks input into tokens using a delimiter pattern (default: whitespace).
Basic Scanner Usage
import java.util.Scanner;
public class ScannerBasicDemo {
public static void main(String[] args) {
String input = "42 Hello";
Scanner scanner = new Scanner(input);
int num = scanner.nextInt();
String word = scanner.next();
System.out.println("Number: " + num);
System.out.println("Word: " + word);
System.out.println("Has next: " + scanner.hasNext());
scanner.close();
}
}
Reading Primitive Types
import java.util.Scanner;
public class ScannerTypesDemo {
public static void main(String[] args) {
String data = "100 3.14 true 25";
Scanner sc = new Scanner(data);
int i = sc.nextInt();
double d = sc.nextDouble();
boolean b = sc.nextBoolean();
long l = sc.nextLong();
System.out.println(i + ", " + d + ", " + b + ", " + l);
sc.close();
}
}
Custom Delimiters
import java.util.Scanner;
public class ScannerDelimiterDemo {
public static void main(String[] args) {
String csv = "one,two,three,four";
Scanner sc = new Scanner(csv).useDelimiter(",");
while (sc.hasNext()) {
System.out.println(sc.next());
}
sc.close();
}
}
Input Sources
import java.io.*;
import java.util.Scanner;
public class ScannerSourcesDemo {
public static void main(String[] args) throws IOException {
Scanner fromString = new Scanner("alpha beta");
System.out.println("String source: " + fromString.next());
fromString.close();
StringReader reader = new StringReader("line1\nline2");
Scanner fromReader = new Scanner(reader);
System.out.println("Reader line: " + fromReader.nextLine());
fromReader.close();
}
}
Pattern Matching
import java.util.Scanner;
import java.util.regex.MatchResult;
public class ScannerPatternDemo {
public static void main(String[] args) {
String text = "Order ID: 12345 Amount: 99.50";
Scanner sc = new Scanner(text);
if (sc.findInLine("ID: (\d+)") != null) {
MatchResult mr = sc.match();
System.out.println("ID token: " + mr.group(1));
}
sc.close();
}
}
Try-With-Resources
import java.util.Scanner;
public class ScannerTryWithResources {
public static void main(String[] args) {
try (Scanner sc = new Scanner("auto close demo")) {
System.out.println(sc.nextLine());
}
}
}
java.util.Random & ThreadLocalRandom
Generate pseudo-random numbers for simulations, games, and sampling.
Basic Random Usage
import java.util.Random;
public class RandomBasicDemo {
public static void main(String[] args) {
Random random = new Random();
System.out.println("nextInt: " + random.nextInt(100));
System.out.println("nextDouble: " + random.nextDouble());
System.out.println("nextBoolean: " + random.nextBoolean());
System.out.println("nextGaussian: " + random.nextGaussian());
}
}
Seeded Random
import java.util.Random;
public class RandomSeededDemo {
public static void main(String[] args) {
Random r1 = new Random(42L);
Random r2 = new Random(42L);
System.out.println("Same seed r1: " + r1.nextInt(1000));
System.out.println("Same seed r2: " + r2.nextInt(1000));
}
}
Random Selection
import java.util.*;
public class RandomSelectionDemo {
public static void main(String[] args) {
List<String> items = new ArrayList<>(Arrays.asList("A", "B", "C", "D"));
Random random = new Random();
String pick = items.get(random.nextInt(items.size()));
System.out.println("Random pick: " + pick);
Collections.shuffle(items, random);
System.out.println("Shuffled: " + items);
}
}
Random Streams (Java 8+)
import java.util.Random;
public class RandomStreamsDemo {
public static void main(String[] args) {
Random random = new Random();
random.ints(5, 1, 10).forEach(n -> System.out.print(n + " "));
System.out.println();
random.doubles(3, 0.0, 1.0).forEach(d -> System.out.printf("%.3f ", d));
System.out.println();
}
}
ThreadLocalRandom
import java.util.concurrent.ThreadLocalRandom;
public class ThreadLocalRandomDemo {
public static void main(String[] args) {
ThreadLocalRandom tlr = ThreadLocalRandom.current();
System.out.println("nextInt: " + tlr.nextInt(1, 101));
System.out.println("nextDouble: " + tlr.nextDouble(0.0, 1.0));
System.out.println("nextLong: " + tlr.nextLong());
}
}
java.util.UUID
Universally unique identifiers for entities, sessions, and database keys.
UUID Basics
import java.util.UUID;
public class UUIDBasicDemo {
public static void main(String[] args) {
UUID random = UUID.randomUUID();
System.out.println("randomUUID: " + random);
UUID parsed = UUID.fromString(random.toString());
System.out.println("fromString: " + parsed);
UUID nameBased = UUID.nameUUIDFromBytes("nikhil-learnhub".getBytes());
System.out.println("nameUUIDFromBytes: " + nameBased);
}
}
java.util.Properties
Key-value configuration maps, often loaded from .properties files.
Properties Basics
import java.io.*;
import java.util.Properties;
public class PropertiesBasicDemo {
public static void main(String[] args) throws IOException {
Properties props = new Properties();
props.setProperty("app.name", "LearnHub");
props.setProperty("app.version", "1.0");
System.out.println("getProperty: " + props.getProperty("app.name"));
StringWriter writer = new StringWriter();
props.store(writer, "Demo Properties");
System.out.println(writer);
Properties loaded = new Properties();
loaded.load(new StringReader("key=value\n"));
System.out.println("loaded: " + loaded.getProperty("key"));
}
}
java.util.StringTokenizer
Legacy tokenizer for splitting strings (prefer String.split or Scanner in new code).
StringTokenizer Demo
import java.util.StringTokenizer;
public class StringTokenizerDemo {
public static void main(String[] args) {
String data = "Java:is:powerful";
StringTokenizer st = new StringTokenizer(data, ":");
while (st.hasMoreTokens()) {
System.out.println(st.nextToken());
}
StringTokenizer st2 = new StringTokenizer("one two three");
System.out.println("countTokens: " + st2.countTokens());
}
}
java.util.Optional (Java 8+)
Optional reduces null checks by modeling values that may be absent.
Optional Basics
import java.util.Optional;
public class OptionalBasicDemo {
public static void main(String[] args) {
Optional<String> present = Optional.of("Java");
Optional<String> empty = Optional.empty();
System.out.println("orElse: " + empty.orElse("fallback"));
Optional<String> mapped = present.map(String::toUpperCase);
System.out.println("map: " + mapped.orElse(""));
Optional<String> filtered = present.filter(s -> s.length() > 3);
filtered.ifPresent(v -> System.out.println("ifPresent: " + v));
System.out.println("orElseGet: " + empty.orElseGet(() -> "generated"));
}
}
Complete Examples
Combine Scanner, Properties, Collections, and Optional in one workflow.
Integrated Utility Example
import java.io.*;
import java.util.*;
public class CompleteExamplesDemo {
public static void main(String[] args) throws IOException {
String config = "theme=dark\nlang=en";
Properties props = new Properties();
props.load(new StringReader(config));
String input = "42 admin";
try (Scanner sc = new Scanner(input)) {
int id = sc.nextInt();
String role = sc.next();
List<String> roles = new ArrayList<>(Arrays.asList(role, "guest"));
Collections.sort(roles);
Optional<String> theme = Optional.ofNullable(props.getProperty("theme"));
System.out.println("User " + id + " roles=" + roles + " theme=" + theme.orElse("default"));
}
}
}