18

I found this:

fun main() {
    val list: MutableList<Int> = mutableListOf(1, 2, 3, 4, 5)

    list.removeAll { x -> x in 1..3 } // [4, 5]
    list.removeIf { x -> x in 1..3 } // [4, 5]
}

Both of them yield the same result.

Though I understand that removeAll is Kotlin and removeIf is Java but I don't understand why removeAll is there when removeIf was already there?

And for the fact that we could use removeIf in Kotlin without any hassle. Or is there any use case that might need one over another?

Willi Mentzel
  • 27,862
  • 20
  • 113
  • 121
Yogesh
  • 453
  • 1
  • 4
  • 12

4 Answers4

15

Java's removeIf() is there since Java 1.8.

Kotlin started at 2011 (wikipedia). Java 1.8 appeared in 2014.

I'm not sure when the Kotlin's removeAll(predicate) was specified and implemented, however it probably predates Java's removeIf().

Willi Mentzel
  • 27,862
  • 20
  • 113
  • 121
Matej
  • 6,004
  • 2
  • 28
  • 27
  • 8
    what follows for Android is that Java's removeIf is only available for API 24+ whereas Kotlin's removeAll will run on older APIs – Maciej Beimcik Jun 13 '19 at 10:50
15

There is one more important difference:

Calling removeIf on a CopyOnWriteArrayList is thread-safe, but removeAll is not.

Looking at the code, removeIf has a custom implementation for CopyOnWriteArrayList, but removeAll iterates over the indices and will end up throwing ArrayIndexOutOfBoundsException or even worse, removing the wrong element, if called concurrently.

Stefan Paul Noack
  • 3,654
  • 1
  • 27
  • 38
7

Those are very very different functions, but in kotlin the method is overloaded, it means, it has two different types of arguments for the function.

If you read the doc, you can see that you can use this function by giving a collection:

fun <T> MutableCollection<out T>.removeAll(
    elements: Collection<T>
): Boolean (source)

Or giving a function to filter:

fun <T> MutableIterable<T>.removeAll(
    predicate: (T) -> Boolean
): Boolean (source)

So, the second one is like the Java version of removeIf, the first one is not.

developer_hatch
  • 15,898
  • 3
  • 42
  • 75
0

Both of them yield the same result.

The result is achieved in completely different ways, so it might not always be quite same.

removeAll is a convenience method. It's a simple loop calling removeAt multiple times.

removeIf is a native ArrayList method that directly manipulates internal elementData, bypassing all the older removal methods and any logic that might have been put there. The bad news here is that it got retroactively blanket-applied to everything that derives from ArrayList, disregarding older implementations.

Or is there any use case that might need one over another?

One example is androidx.databinding.ObservableList, which predates removeIf, and doesn't send due removal notifications, thus either breaking your code silently or causing cryptic errors.

Agent_L
  • 4,960
  • 28
  • 30