Selft training repo
The addition of generics in Java 5 brought significant enhancements to the Collections Framework.
The diamond operator is a feature introduced in Java 7 to simplify the usage of generics in collections.
Common usage of the Collections API in modern Java:
The List interface represents an ordered collection of elements and allows duplicate elements.
Common implementations include: ArrayList
and LinkedList
.
List<String> list = new ArrayList<>();
list.add("Java");
list.add("Python");
list.add("C++");
System.out.println(list); // Output: [Java, Python, C++]
The Set interface represents an unordered collection of elements with no duplicates.
Common implementations include: HashSet
and TreeSet
.
Set<Integer> set = new HashSet<>();
set.add(1);
set.add(2);
set.add(1); // This will not be added as duplicates are not allowed
System.out.println(set); // Output: [1, 2]
The Map interface represents a mapping of keys to values, where each key is unique.
Common implementations include HashMap
and TreeMap
.
Map<String, Integer> map = new HashMap<>();
map.put("apple", 10);
map.put("orange", 5);
System.out.println(map.get("apple")); // Output: 10
The Queue and Deque interfaces were added to the Java Collections Framework in Java 1.5 (also known as Java 5) as part of the major enhancements made to the collections API.
The Queue interface represents a collection that holds elements in a specific order. Typically processed in a first-in-first-out (FIFO) manner
The Deque interface interface extends the Queue
interface and represents a queue where you can add or remove elements from both ends first-in-first-out (FIFO) and last-in-first-out (LIFO). You can treat a Deque
as both a queue and a stack
Common implementations include: LinkedList
and PriorityQueue
.
Queue<String> queue = new LinkedList<>();
queue.offer("First");
queue.offer("Second");
System.out.println(queue.poll()); // Output: First
Type | duplicate elements? | ordered? | keys and values? | add/remove in order? |
---|---|---|---|---|
List | Yes | Yes (by index) | No | No |
Map | Yes (for values) | No | Yes | No |
Queue | Yes | Yes (retrieved in defined order) | No | Yes |
Set | No | No | No | No |
Comparing objects in Java 8 collections typically involves implementing the Comparable
interface or using a custom Comparator
to define the comparison logic.
The Comparable interface allows you to define a natural ordering for the elements in a collection. To use this interface, the class of the objects you want to compare must implement it and override the compareTo()
method.
Example of implementing Comparable:
public class Person implements Comparable<Person> {
private String name;
private int age;
// Constructors, getters, setters
@Override
public int compareTo(Person otherPerson) {
return this.name.compareTo(otherPerson.name);
}
}
When you implement the Comparable interface in a class, you introduce new logic to determine equality between objects. The compareTo()
method is used, and it returns 0 if two objects are considered equal, whereas the equals()
method returns true if the two objects are equal.
It is highly recommended to ensure that your Comparable classes follow this consistency with the equals() method because some collection classes may not behave predictably if the compareTo() and equals() methods are not consistent
If the class you want to compare does not implement the Comparable
interface or if you want to define multiple comparison criteria, you can use a custom Comparator
. A Comparator
allows you to specify different comparison logic for a class without modifying the original class.
Example of using Comparator:
public class PersonAgeComparator implements Comparator<Person> {
@Override
public int compare(Person person1, Person person2) {
return Integer.compare(person1.getAge(), person2.getAge());
}
}
Sorting a collection in Java 8 can be done using the sort()
method provided by the List interface. For custom sorting, you can pass a Comparator
as an argument to the sort() method.
Comparable
:List<Person> personList = new ArrayList<>();
// Add elements to the list
Collections.sort(personList); // This will use the natural order defined by the compareTo method in the Person class
Comparator
:Considering this implementation of PersonAgeComparator:
import java.util.Comparator;
public class PersonAgeComparator implements Comparator<Person> {
@Override
public int compare(Person person1, Person person2) {
// Compare by age (ascending order)
return Integer.compare(person1.getAge(), person2.getAge());
}
}
Sorting by it will be:
List<Person> personList = new ArrayList<>();
// Add elements to the list
personList.add(new Person("Alice", 25));
personList.add(new Person("Bob", 20));
personList.add(new Person("Charlie", 30));
Comparator<Person> ageComparator = new PersonAgeComparator();
Collections.sort(personList, ageComparator); // This will sort the list based on the age field
// Now the personList is sorted based on age (ascending order)
for (Person person : personList) {
System.out.println(person.getName() + " - Age: " + person.getAge());
}
Output:
Bob - Age: 20
Alice - Age: 25
Charlie - Age: 30
In Java 8, the List interface also has a new sort() method that takes a Comparator directly:
List<Person> personList = new ArrayList<>();
// Add elements to the list
personList.sort(ageComparator);
And also Comparator implementation can be reduced by calling Comparator
utility method comparing
or comparingInt
in this case, plus method reference for Person
method getAge()
:
personList.sort(Comparator.comparingInt(Person::getAge));
Finally:
public static void main(String[] args) {
List<Person> personList = new ArrayList<>();
// Add elements to the list (example data)
personList.add(new Person("Alice", 25));
personList.add(new Person("Bob", 20));
personList.add(new Person("Charlie", 30));
personList.sort(Comparator.comparing(Person::getAge));
// Now the personList is sorted based on age (ascending order)
for (Person person : personList) {
System.out.println(person.getName() + " - Age: " + person.getAge());
}
}
The Collections class offers methods for binary search, finding max/min elements, reversing collections, and more.
List<Integer> numbers = Arrays.asList(5, 2, 8, 1, 6);
int index = Collections.binarySearch(numbers, 8);
System.out.println(index); // Output: 4 (index of element 8)
int maxElement = Collections.max(numbers);
System.out.println(maxElement); // Output: 8
Binary search requires that the list be sorted in ascending order before performing the search.
import java.util.*;
public class BinarySearchExample {
public static void main(String[] args) {
List<Integer> numbers = Arrays.asList(1, 3, 5, 7, 9, 11, 13, 15, 17, 19);
int index = Collections.binarySearch(numbers, 9);
if (index >= 0) {
System.out.println("Element found at index: " + index);
} else {
System.out.println("Element not found.");
}
}
}
Output:
Element found at index: 4
To find the maximum and minimum elements in a collection, you can use Collections.max()
and Collections.min()
methods.
import java.util.*;
public class MaxMinExample {
public static void main(String[] args) {
List<Integer> numbers = Arrays.asList(10, 2, 8, 4, 6);
int max = Collections.max(numbers);
int min = Collections.min(numbers);
System.out.println("Max: " + max);
System.out.println("Min: " + min);
}
}
Output:
Max: 10
Min: 2
To reverse the order of elements in a list, you can use the Collections.reverse()
method.
import java.util.*;
public class ReverseExample {
public static void main(String[] args) {
List<Integer> numbers = new ArrayList<>(Arrays.asList(1, 2, 3, 4, 5));
System.out.println("Original List: " + numbers);
Collections.reverse(numbers);
System.out.println("Reversed List: " + numbers);
}
}
Output:
Original List: [1, 2, 3, 4, 5]
Reversed List: [5, 4, 3, 2, 1]
You can use Collections.frequency()
to count the occurrences of an element in a collection.
import java.util.*;
public class FrequencyExample {
public static void main(String[] args) {
List<String> words = Arrays.asList("apple", "banana", "orange", "apple", "grape");
int frequency = Collections.frequency(words, "apple");
System.out.println("Frequency of 'apple': " + frequency);
}
}
Output:
Frequency of 'apple': 2
If you need to search or perform other operations with a custom sorting order, you can use the Collections.binarySearch()
and other methods that take a Comparator as an argument.
Suppose we have a list of strings representing names, and we want to perform a binary search to find a specific name in the list, but we want the search to be case-insensitive. For that, we can use a custom comparator that ignores the case when comparing strings
import java.util.*;
public class CustomComparatorExample {
public static void main(String[] args) {
List<String> names = Arrays.asList("John", "Alice", "bob", "Tom", "jane", "Michael");
String targetName = "Jane";
// Sorting the list in a case-insensitive manner using a custom comparator
Collections.sort(names, new CaseInsensitiveComparator());
// Performing binary search with custom comparator
int index = Collections.binarySearch(names, targetName, new CaseInsensitiveComparator());
if (index >= 0) {
System.out.println("Name found at index: " + index);
System.out.println(names);
System.out.println(names.get(index));
} else {
System.out.println("Name not found.");
}
}
// Custom Comparator that ignores the case of strings during comparison
static class CaseInsensitiveComparator implements Comparator<String> {
@Override
public int compare(String str1, String str2) {
return str1.compareToIgnoreCase(str2);
}
}
}
Output:
Name found at index: 2
[Alice, bob, jane, John, Michael, Tom]
jane
Apart from Collections.binarySearch()
that takes a Comparator
as an argument for custom sorting order, there are several other methods in the Java Collections framework that also accept a `Comparator to customize the sorting and searching behavior. Some of these methods include:
Collections.sort(List<T> list, Comparator<? super T> c)
:
Sorts the elements of the list using the specified Comparator.
Collections.sort(List<T> list, int fromIndex, int toIndex, Comparator<? super T> c)
:
Sorts the specified range of elements in the list using the specified Comparator.
Collections.binarySearch(List<? extends T> list, T key, Comparator<? super T> c)
: Searches for the specified element in the list using the specified Comparator.
Max/Min Methods:
Collections.max(Collection<? extends T> coll, Comparator<? super T> c)
: Returns the maximum element of the given collection according to the provided Comparator.
Collections.min(Collection<? extends T> coll, Comparator<? super T> c)
: Returns the minimum element of the given collection according to the provided Comparator.
Collections.indexOfSubList(List<?> source, List<?> target, Comparator<?> c)
: Returns the starting index of the first occurrence of the target sublist within the source list using the specified Comparator.https://www.geeksforgeeks.org/how-to-learn-java-collections-a-complete-guide/
Get Started | Languages | Java Development | Java 7