79 lines
4.0 KiB
Plaintext
79 lines
4.0 KiB
Plaintext
![]() |
The `kotlin.collections` package offers many functions to interact with collections.
|
||
|
In particular, functions `find(predicate)`, `findLast(predicate)`, `firstOrNull(predicate)` and "`lastOrNull(predicate)` return the element that matches the given predicate.
|
||
|
|
||
|
== Why is this an issue?
|
||
|
|
||
|
The functions `find(predicate)`, `findLast(predicate)`, `firstOrNull(predicate)` and "`lastOrNull(predicate)`
|
||
|
can be improperly used to check the presence of an element that matches the given predicate.
|
||
|
In such cases the code is more difficult to read and understand than it would be with the functions `any(predicate)`, `none(predicate)` or `contains(element)`.
|
||
|
|
||
|
=== What is the potential impact?
|
||
|
|
||
|
The pattern of using `find(predicate)`, `findLast(predicate)`, `firstOrNull(predicate)` and "`lastOrNull(predicate)` combined with a null check,
|
||
|
to check the presence of an element is not immediately clear to readers.
|
||
|
For example, the expression `list.find { it > 5 } != null` is more difficult to understand than `list.any { it > 5 }`.
|
||
|
The additional comparison operator increases the complexity of the expression and introduces confusion about the intent of the code.
|
||
|
|
||
|
== How to fix it
|
||
|
|
||
|
Replace the use of `find(predicate)`, `findLast(predicate)`, `firstOrNull(predicate)` and "`lastOrNull(predicate)` with `any(predicate)`, `none(predicate)` or `contains(element)`.
|
||
|
|
||
|
There are four possible scenarios:
|
||
|
|
||
|
1. The predicate is a simple binary expression checking for equality, and the found object is compared to not be `null`:
|
||
|
- Replace `find { it == element } != null` with `contains(element)`.
|
||
|
- Replace `findLast { it == element } != null` with `contains(element)`.
|
||
|
- Replace `firstOrNull { x -> x == element } != null` with `contains(element)`.
|
||
|
- Replace `lastOrNull { x -> x == element } != null` with `contains(element)`.
|
||
|
|
||
|
2. The predicate is a simple binary expression checking for equality, and the found object is compared to be `null`:
|
||
|
- Replace `find { it == element } == null` with `!contains(element)`.
|
||
|
- Replace `findLast { it == element } == null` with `!contains(element)`.
|
||
|
- Replace `firstOrNull { x -> x == element } == null` with `!contains(element)`.
|
||
|
- Replace `lastOrNull { x -> x == element } == null` with `!contains(element)`.
|
||
|
|
||
|
3. The predicate is any binary expression not checking for equality, and the found object is compared to not be `null`:
|
||
|
- Replace `find { it > 5 } != null` with `any { it > 5 }`.
|
||
|
- Replace `findLast { it != 5 } != null` with `any { it != 5 }`.
|
||
|
- Replace `firstOrNull { x -> x < 5 } != null` with `any { x -> x < 5 }`.
|
||
|
- Replace `lastOrNull { x -> x != 5 } != null` with `any { x -> x != 5 }`.
|
||
|
|
||
|
4. The predicate is any binary expression not checking for equality, and the found object is compared to be `null`:
|
||
|
- Replace `find { it > 5 } == null` with `none { it > 5 }`.
|
||
|
- Replace `findLast { it != 5 } == null` with `none { it != 5 }`.
|
||
|
- Replace `firstOrNull { x -> x < 5 } == null` with `none { x -> x < 5 }`.
|
||
|
- Replace `lastOrNull { x -> x != 5 } == null` with `none { x -> x != 5 }`.
|
||
|
|
||
|
=== Code examples
|
||
|
|
||
|
==== Noncompliant code example
|
||
|
|
||
|
[source,kotlin,diff-id=1,diff-type=noncompliant]
|
||
|
----
|
||
|
fun example(list: List<Int>) {
|
||
|
list.find { it > 5 } != null // Noncompliant
|
||
|
list.findLast { it > 5 } == null // Noncompliant
|
||
|
list.firstOrNull { it == 5 } != null // Noncompliant
|
||
|
list.lastOrNull { x -> x == 5 } != null // Noncompliant
|
||
|
list.find { x -> 5 == 4 } != null // Noncompliant, note that this case cannot be fixed using contains
|
||
|
}
|
||
|
----
|
||
|
|
||
|
==== Compliant solution
|
||
|
|
||
|
[source,kotlin,diff-id=1,diff-type=compliant]
|
||
|
----
|
||
|
fun example(list: List<Int>) {
|
||
|
list.any { it > 5 } // Compliant
|
||
|
list.none { it > 5 } // Compliant
|
||
|
list.contains(5) // Compliant
|
||
|
!list.contains(5) // Compliant
|
||
|
list.any { x -> 5 == 4 } // Compliant, note that this case cannot be fixed using contains
|
||
|
}
|
||
|
----
|
||
|
|
||
|
== Resources
|
||
|
|
||
|
=== Documentation
|
||
|
|
||
|
* https://kotlinlang.org/api/latest/jvm/stdlib/kotlin.collections/[Kotlin API Docs, Package kotlin.collections]
|