This tutorial shows you how to sort enum values based on natural ordering, enum name, or custom ordering.
Java supports enum data type, which is used to store a finite set of values. One of the advantages of using enum is you can ensure that you only use allowed values. In addition, it also prevents errors caused by typo. If you have a collection or array of enum values and you need to sort them, you can read this tutorial to understand what is the default ordering and how to create a custom ordering.
For this tutorial, we are going to use the enum below.
public enum Status {
PENDING(3),
PROCESSED(4),
SHIPPED(2),
DELIVERED(1),
;
private final int priority;
Status(int priority) {
this.priority = priority;
}
public int getPriority() {
return this.priority;
}
}
Order by Natural Ordering
The natural ordering of Java enums is by the order of the values declared in the enum. If you have a Collection
and try to sort it without specifying a Comparator
, the values will be sorted based on their order of how they are declared in the enum. It's the same as the ordinal()
property value. For an array, you can call the sort
method to sort the values based on the natural order.
Collection<Status> naturalOrderResult = statuses.stream()
.sorted()
.toList();
System.out.println(naturalOrderResult);
// Output: [PENDING, PROCESSED, SHIPPED, DELIVERED]
Arrays.sort(statusesArr);
System.out.println(Arrays.asList(statusesArr));
// Output: [PENDING, PROCESSED, SHIPPED, DELIVERED]
Order by Name
If you want to order the values alphabetically based on the name, you can use a Comparator
which compares the name. Java enums have name()
property which returns the enum name as a string. You can pass the field to the Comparator.comparing
method.
Collection<Status> nameOrderResult = statuses.stream()
.sorted(Comparator.comparing(Status::name))
.toList();
System.out.println(nameOrderResult);
// Output: [DELIVERED, PENDING, PROCESSED, SHIPPED]
Arrays.sort(statusesArr, Comparator.comparing(Status::name));
System.out.println(Arrays.asList(statusesArr));
// Output: [DELIVERED, PENDING, PROCESSED, SHIPPED]
Order by Property
If you need to use a custom ordering, add an additional field in the enum along with the getter of the field. Then, you can pass the getter property to the Comparator.comparing
method.
Collection<Status> propertyOrderResult = statuses.stream()
.sorted(Comparator.comparing(Status::getPriority))
.toList();
System.out.println(propertyOrderResult);
// Output: [DELIVERED, SHIPPED, PENDING, PROCESSED]
Arrays.sort(statusesArr, Comparator.comparing(Status::getPriority));
System.out.println(Arrays.asList(statusesArr));
// Output: [DELIVERED, SHIPPED, PENDING, PROCESSED]
Another alternative is by creating a custom class that extends Comparator
. It requires you to override the compare
method.
import java.util.Comparator;
public class StatusComparator implements Comparator<Status> {
@Override
public int compare(Status o1, Status o2) {
return Integer.compare(o1.getPriority(), o2.getPriority());
}
}
Then, pass an instance of the class as the Comparator
. You can re-use the class as many times as you want.
Collection<Status> comparatorOrderResult = statuses.stream()
.sorted(new StatusComparator())
.toList();
System.out.println(comparatorOrderResult);
// Output: [DELIVERED, SHIPPED, PENDING, PROCESSED]
Arrays.sort(statusesArr, new StatusComparator());
System.out.println(Arrays.asList(statusesArr));
// Output: [DELIVERED, SHIPPED, PENDING, PROCESSED]
By design, Java makes the compareTo
method of the Enum
class final, so that it's always consistent that the natural ordering is always based on the declaration order.
Order Collection By Enum Value
If you have a collection or array whose elements contain an enum property, you can sort the collection or array elements based on the enum value. For example, there is a class whose one of the properties returns the enum above.
@AllArgsConstructor
@NoArgsConstructor
@Getter
@Setter
public class Item {
private String name;
private Status status;
}
Below is a collection that holds the instances of the class above.
Collection<Item> items = List.of(
new Item("Laptop", Status.PENDING),
new Item("Phone", Status.DELIVERED),
new Item("Keyboard", Status.PROCESSED),
new Item("Mouse", Status.SHIPPED)
);
To sort based on the natural ordering, use the getStatus
function as the comparator.
Collection<Item> itemsSortedByEnum = items.stream()
.sorted(Comparator.comparing(Item::getStatus))
.toList();
for (Item item : itemsSortedByEnum) {
System.out.printf("Item: %s, status: %s\n", item.getName(), item.getStatus());
}
// Output:
// Item: Laptop, status: PENDING
// Item: Keyboard, status: PROCESSED
// Item: Mouse, status: SHIPPED
// Item: Phone, status: DELIVERED
It's also possible to sort based on any of the enum's properties. Below is another example that sorts based on the getPriority
property.
Collection<Item> itemsSortedByEnumProperty = items.stream()
.sorted(Comparator.comparing(item -> item.getStatus().getPriority()))
.toList();
for (Item item : itemsSortedByEnumProperty) {
System.out.printf("Item: %s, status: %s\n", item.getName(), item.getStatus());
}
// Output:
// Item: Phone, status: DELIVERED
// Item: Mouse, status: SHIPPED
// Item: Laptop, status: PENDING
// Item: Keyboard, status: PROCESSED
Summary
The default ordering of enum values is based on the order of how the values are declared. However, it's also possible to sort based on the name or any property of the enum by using a custom Comparator
.