UPDATE 2024.06.16:
After an awesome comment from Emmanuel Bourg, I took another look at the code and upgraded it to be modern-style null safe, and incorporating his excellent suggestion. The original code is captured below the last horizontal rule.
It's considerably more aligned with the latest versions of Java, i.e., exploiting null is a type-hole, mutating a method parameter is a type-hole code smell, and mutability being restricted to as small a block of code within a single method as possible to improve FP composability (as opposed to the weaker and error-prone OOP reusability).
For anyone on Java 21 or later, use List.reversed().
For anyone on Java 8 through Java 20 who...
- Wants to guard against
null
- Does not want to modify the passed parameter,
List<T> (a strong code smell)
- Wants to return an unmodifiable
List<T>
- Does not want to use a third-party library like Guava
- Wants a function that follows the Java Collection API
Stream<T>'s fluent calling style
- Wants to see modern style code (and to move away from the very C-like code from the late 1990s)
- Wants to move towards expressions (and to move away from statements)
- Wants to avoid reimplementing as much as possible (in this case, by calling the mutation-oriented imperative method,
Collections.reverse(), already present in the Java Collections API)
...here's a useful solution I've generated:
/**
* Returns a {@link Collections#unmodifiableList} with the contained instances in reverse order.
*
* @param list the list to copy from while reversing ({@code null} safe)
* @param <T> the type of instances contained in the {@link list}
* @return a {@link Collections#unmodifiableList} with the contained instances in reverse order
*/
public static <T> List<T> reverse(List<T> list) {
return Optional.ofNullable(list)
.filter(listNonNull ->
!listNonNull.isEmpty())
.map(listNonEmpty -> {
if (listNonEmpty.size() == 1) {
return Collections.unmodifiableList(listNonEmpty);
}
var listNonEmptyCopy = new ArrayList<>(listNonEmpty);
Collections.reverse(listNonEmptyCopy);
return Collections.unmodifiableList(listNonEmptyCopy);
})
.orElse(List.of());
}
Originally Posted Code that was updated above (DO NOT USE):
/**
* Reverse the order of the instances returning an unmodifiable list.
*
* @param list the list to copy from while reversing
* @param <T> the type of instances contained in the list
* @return an unmodifiable list with the contained instances in reverse order
*/
public static <T> List<T> reverse(List<T> list) {
if (list.size() > 1) {
var size = list.size();
return IntStream.range(0, size)
.mapToObj(index -> list.get(size - 1 - index))
.toList();
} else if (list.size() == 1) {
return list;
}
return List.of();
}
Collections.reverse(list)List.reverse()is available since Java 21.Collections.reverse(List<?> list)in a return statement expectingList<?>because : The Collections.reverse method does not return a new list ; instead, it modifies the given list in place and returns void. As a result, you cannot use it directly in a return statement.