A Collection is a group of objects that can be of homogenous data type or heterogeneous data type. Homogeneous means same data type and Heterogenous means different data types. A class is a heterogeneous data type because it can contain different data types like int, double, String and may also contain other classes. There are different types of collections in Java - ArrayList, TreeSet, HashSet, HashTable
are a few example. The java.util.Collections
contains methods to perform various operations on a collection. One of those methods is the sort method which sorts the elements of a collection in ascending order. For example, to sort a collection of strings,
// Defind a collection of string ArrayList<String> fruits = new ArrayList<String>(); // Add elements to the collection fruits.add("Grapes"); fruits.add("Orange"); fruits.add("Apple"); fruits.add("Cherry"); // Sort Collections.sort(fruits); // Print all elements for (String fruit : fruits) System.out.printf("%s ", fruit);
Apple Cherry Grapes Orange
Sorting a collection of user-defined objects
Consider a class named Part
which consists of the attributes, number and name.
public class Part { int number; String name; public Part(int number, String name) { this.number = number; this.name = name; } }
Create a collection of Part objects and try calling the sort method.
ArrayList<Part> partsList = new ArrayList<Part>(); partsList.add(new Part(19500, "Brake Pads")); partsList.add(new Part(11502, "Wiper Blade")); partsList.add(new Part(18021, "Abs Sensor")); partsList.add(new Part(14235, "Ignition Lead")); Collections.sort(partsList);
The following error is thrown when you compile this code
java: no suitable method found for sort(java.util.ArrayList<Part>)
method java.util.Collections.sort(java.util.List<T>) is not applicable
(inference variable T has incompatible bounds
equality constraints: Part
lower bounds: java.lang.Comparable<? super T>)
method java.util.Collections.<T>sort(java.util.List<T>,java.util.Comparator<? super T>) is not applicable
(cannot infer type-variable(s) T
(actual and formal argument lists differ in length))
This is because, the sort method expects the list that is passed to implement the Comparable
interface in its class.
The comparable
interface is used to sort user-defined class objects and it contains a single method
int compareTo(T obj)
The compareTo
method compares this(current) object with the object that is specified. It returns,
- a negative integer value if this object is less than specified object.
- zero, if the objects are equal.
- a positive integer if the current object is greater.
Here is how to implement Comparable on the Part class to compare the Part names. The String
data type already has a compareTo
method to compare two strings, so this can be used in the compareTo method for the Parts.
public class Part implements Comparable<Part> { int number; String name; public Part(int number, String name) { this.number = number; this.name = name; } @Override public int compareTo( Part p){ return name.compareTo(p.name); } }
Now you can call the Collections.sort
method to sort the parts in ascending order.
ArrayList<Part> partsList = new ArrayList<Part>(); partsList.add(new Part(19500, "Brake Pads")); partsList.add(new Part(11502, "Wiper Blade")); partsList.add(new Part(18021, "Abs Sensor")); partsList.add(new Part(14235, "Ignition Lead")); // Sort Collections.sort(partsList); // Print for (Part p : partsList) System.out.println("[" + p.number + " " + p.name + "]");
Outputs
[18021 Abs Sensor] [19500 Brake Pads] [14235 Ignition Lead] [11502 Wiper Blade]
To sort the collection based on on Part Id, change the compareTo
method as below.
public int compareTo( Part p){ return this.number - p.number; }
Sorting collections using Comparator interface
Comparator is an interface similar to Comparable and can be used to sort the elements of a collection. It is part of the java.utils
pacakage and has to be imported first. Here is an example which implements two sorting sequences using Comparator.
// Import Comparator class import java.util.Comparator; ComparatornameSort = new Comparator () { @Override public int compare(Part o1, Part o2) { return o1.name.compareTo(o2.name); } }; Comparator numberSort = new Comparator () { @Override public int compare(Part o1, Part o2) { return o1.number - o2.number; } }; // Call sort method with nameSort comparator Collections.sort(partsList, nameSort); // Call sort method with numberSort comparator Collections.sort(partsList, numberSort);
Difference between Comparable and Compares
Comparable is part of the | Comparator is part of the |
Comparable compares "this" object to the specified object. | Comparator compares the two objects that are specified. |
Comparable interface has | Comparator has |
The syntax for sort method when using Comparable is | The syntax for sort method when using Comparator is |
Use Comparable to implement default sorting. | Use Comparator when you want to sort a collection in differnt ways. |
Sorting a collection on multiple fields
You can use Comparable and Comparator interfaces to sort a collection on multiple fields. The example below shows sorting the Parts collection based name and number. In other words, the collection is sorted by Part name first, and if there are duplicate elements with the same name then they are sorted by Part number.
@Override public int compareTo( Part p){ int order = name.compareTo(p.name); if (order == 0) order = number - p.number; return order; }
Using Comparator
ComparatornameNumberSort = new Comparator () { @Override public int compare(Part o1, Part o2) { int order = o1.name.compareTo(o2.name); if (order == 0 ) order = o1.number - o2.number; return order; } };