
1. Introduction
In this tutorial, we’ll explore how to sort Long values using the Collections.sort() method. Java provides a simple way to sort lists, but when dealing with Long values, we need to understand how Java compares objects.
2. Understanding Natural Ordering for Long Values
The Collections.sort() method sorts elements in their natural order by default. For numerical types like Long, natural ordering arranges values from smallest to largest. This works seamlessly because the Long class implements the Comparable interface, which defines the intrinsic sorting behavior.
For example, when comparing 500L and 200L using the compareTo() method:
Long a = 500L;
Long b = 200L;
int result = a.compareTo(b);
// result > 0 because 500 > 200
This natural ordering is used by default in methods like Collections.sort() when no explicit comparator is provided. Let’s look at an example that compares Long values based on their natural ordering:
List<Long> numbers = new ArrayList<>(Arrays.asList(500L, 200L, 800L));
Collections.sort(numbers);
assertEquals(Arrays.asList(200L, 500L, 800L), numbers);
When Collections.sort() is called, Java internally uses the compareTo() method to compare the elements. The compareTo() method for Long works as follows:
- If a < b, it returns a negative number
- If a == b, it returns zero
- If a > b, it returns a positive number.
This approach is straightforward and ideal for most use cases where ascending order is required, such as arranging transaction amounts or sorting timestamps in chronological order.
3. Comparing Long Values in Descending Order Using a Comparator
If we want to reverse the natural comparison order, we can use Comparator.reverseOrder(), which compares the Long values in descending order. This provides an alternative to modifying the underlying comparison logic directly.
Let’s see how to compare Long values in descending order:
Collections.sort(numbers, Comparator.reverseOrder());
assertEquals(Arrays.asList(800L, 500L, 200L), numbers);
The Comparator.reverseOrder() comparator reverses the natural comparison, ensuring that the Long values are compared in descending order without needing to manually implement a comparator.
4. Creating Custom Comparing Logic with a Comparator
Beyond simple ascending or descending comparisons, we can also create a custom Comparator if we need more control over sorting. For instance, arranging values in descending order or prioritizing certain numbers (for example, even numbers first) demands custom logic.
Java’s Comparator interface allows us to define these rules explicitly. A Comparator acts as a blueprint for comparing two elements, enabling flexible sorting strategies beyond natural ordering.
Suppose we want to compare Long values based on their distance from a target value, such as 400L. Let’s create a custom Comparator for this requirement:
List<Long> numbers = new ArrayList<>(Arrays.asList(500L, 200L, 800L));
long target = 400L;
Collections.sort(numbers, (a, b) -> {
long distanceA = Math.abs(a - target);
long distanceB = Math.abs(b - target);
return Long.compare(distanceA, distanceB);
});
assertEquals(Arrays.asList(500L, 200L, 800L), numbers);
In this example, the comparison logic is based on the distance of each Long value from our target value of 400L. The comparator calculates the absolute difference between each Long value and the target and then compares these distances.
5. Comparing Long Values with Multiple Criteria
In some scenarios, we may want to compare Long values based on multiple criteria. For example, we may want to sort Long values by their absolute value or by other business rules. This can be accomplished using multiple comparator conditions.
Let’s consider a scenario where we need to first sort by the absolute value and, in the case of ties, by the original value. This can be done by chaining comparators:
List<Long> numbers = new ArrayList<>(Arrays.asList(-500L, 200L, -800L, 300L));
Collections.sort(numbers, Comparator.comparingLong(n -> Math.abs((Long) n))
.thenComparingLong(n -> (Long) n));
assertEquals(Arrays.asList(200L, 300L, -500L, -800L), numbers);
The thenComparing() method is used to add a secondary comparison criterion. In this case, the Long values are first compared by absolute value using Comparator.comparingLong(Math::abs). If two values have the same absolute value, the original values are compared to break the tie using thenComparingLong(Long::longValue).
This approach is particularly useful when there are multiple sorting rules, such as sorting by value and then by timestamp or name.
6. Handling Null Values in Long Comparisons
The Collections.sort() method does not allow nulls by default and will throw a NullPointerException if any null values are present. To handle this, we can use a custom comparator to define how null values should be treated during the comparison process.
We can use Comparator.nullsFirst() to ensure that nulls are placed at the start of the sorted list:
List<Long> numbers = new ArrayList<>(Arrays.asList(500L, null, 200L, 800L));
Collections.sort(numbers, Comparator.nullsFirst(Comparator.naturalOrder()));
assertEquals(Arrays.asList(null, 200L, 500L, 800L), numbers);
Alternatively, we can use Comparator.nullsLast() to position null values at the end of the list:
Collections.sort(numbers, Comparator.nullsLast(Comparator.naturalOrder()));
assertEquals(Arrays.asList(200L, 500L, 800L, null), numbers);
7. Comparing Long Values Based on Custom Object Properties
In many cases, Long values are part of custom objects, and we may need to sort these objects based on the value of a property. For instance, let’s assume we have a Transaction class with a Long field for the transaction amount. We can use a comparator to sort these objects based on the Long value.
Here’s an example:
class Transaction {
private Long amount;
public Transaction(Long amount) {
this.amount = amount;
}
public Long getAmount() {
return amount;
}
}
List<Transaction> transactions = new ArrayList<>();
transactions.add(new Transaction(500L));
transactions.add(new Transaction(200L));
transactions.add(new Transaction(800L));
// Sorting transactions by amount
Collections.sort(transactions, Comparator.comparingLong(Transaction::getAmount));
assertEquals(Arrays.asList(200L, 500L, 800L), transactions.stream().map(Transaction::getAmount).collect(Collectors.toList()));
This code sorts a list of Transaction objects based on their amount field using the Comparator.comparingLong() method. This approach is useful when the Long value is wrapped in a custom object.
8. Conclusion
In this article, we’ve explored various ways to compare Long values using Java’s Collections.sort() method. We discussed natural ordering, custom comparators, handling null values, and comparing based on multiple criteria. These techniques allow us to define precise comparison logic for Long values, whether working with simple lists or custom objects.
As always, the source code is available over on GitHub.
The post Comparing Long Values Using Collections.sort() first appeared on Baeldung.