This rule raises an issue when a loop iterates over a list and replaces each element with a transformed version of itself, instead of using a dedicated list transformation method designed for in-place element replacement.
In Java, this dedicated method is List.replaceAll(), which has been available since Java 8.
Traditional loops that iterate over a list to replace each element with a transformed version are a common pattern in older codebases. While functionally correct, this approach has several drawbacks:
Verbosity: Index-based loops require explicit index management, bounds checking, and manual calls to retrieve and update elements at each position. This adds boilerplate code that obscures the actual intent.
Readability: The loop structure forces readers to mentally parse the iteration mechanics before understanding the transformation logic. The real purpose - applying a function to each element - is hidden within the loop body.
Error-prone: Manual index management introduces opportunities for off-by-one errors or incorrect loop bounds. Even though these are typically caught quickly, they add unnecessary risk.
Modern languages provide dedicated methods for in-place list transformation that address this pattern. These methods:
These transformation methods accept a function that takes an element and returns a transformed element of the same type. This functional approach aligns with modern programming idioms and makes the code more declarative: you specify what transformation to apply rather than how to iterate and apply it.
In Java, the List.replaceAll(UnaryOperator<E> operator) method was introduced in Java 8 to address this pattern. The method
takes a UnaryOperator - a functional interface representing a function that accepts and returns the same type.
Using traditional loops instead of declarative collection transformation methods does not introduce bugs or security vulnerabilities. However, it does impact code maintainability:
In Java, this specifically refers to methods like List.replaceAll() for transforming list elements in place.
Replace the loop with a call to List.replaceAll(). Pass a UnaryOperator that performs the transformation. You can use a
lambda expression or a method reference depending on the complexity of the transformation.
for (int i = 0; i < list.size(); i++) {
list.set(i, list.get(i).toUpperCase()); // Noncompliant
}
list.replaceAll(String::toUpperCase);