kotlin.collections.MutableCollections.kt Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of kotlin-stdlib-common Show documentation
Show all versions of kotlin-stdlib-common Show documentation
Kotlin Common Standard Library (legacy, use kotlin-stdlib instead)
/*
* Copyright 2010-2020 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
@file:kotlin.jvm.JvmMultifileClass
@file:kotlin.jvm.JvmName("CollectionsKt")
package kotlin.collections
/**
* Removes a single instance of the specified element from this
* collection, if it is present.
*
* Allows to overcome type-safety restriction of `remove` that requires to pass an element of type `E`.
*
* @return `true` if the element has been successfully removed; `false` if it was not present in the collection.
*/
@kotlin.internal.InlineOnly
public inline fun <@kotlin.internal.OnlyInputTypes T> MutableCollection.remove(element: T): Boolean =
@Suppress("UNCHECKED_CAST") (this as MutableCollection).remove(element)
/**
* Removes all of this collection's elements that are also contained in the specified collection.
* Allows to overcome type-safety restriction of `removeAll` that requires to pass a collection of type `Collection`.
*
* @return `true` if any of the specified elements was removed from the collection, `false` if the collection was not modified.
*/
@kotlin.internal.InlineOnly
public inline fun <@kotlin.internal.OnlyInputTypes T> MutableCollection.removeAll(elements: Collection): Boolean =
@Suppress("UNCHECKED_CAST") (this as MutableCollection).removeAll(elements)
/**
* Retains only the elements in this collection that are contained in the specified collection.
*
* Allows to overcome type-safety restriction of `retainAll` that requires to pass a collection of type `Collection`.
*
* @return `true` if any element was removed from the collection, `false` if the collection was not modified.
*/
@kotlin.internal.InlineOnly
public inline fun <@kotlin.internal.OnlyInputTypes T> MutableCollection.retainAll(elements: Collection): Boolean =
@Suppress("UNCHECKED_CAST") (this as MutableCollection).retainAll(elements)
/**
* Adds the specified [element] to this mutable collection.
*/
@kotlin.internal.InlineOnly
public inline operator fun MutableCollection.plusAssign(element: T) {
this.add(element)
}
/**
* Adds all elements of the given [elements] collection to this mutable collection.
*/
@kotlin.internal.InlineOnly
public inline operator fun MutableCollection.plusAssign(elements: Iterable) {
this.addAll(elements)
}
/**
* Adds all elements of the given [elements] array to this mutable collection.
*/
@kotlin.internal.InlineOnly
public inline operator fun MutableCollection.plusAssign(elements: Array) {
this.addAll(elements)
}
/**
* Adds all elements of the given [elements] sequence to this mutable collection.
*/
@kotlin.internal.InlineOnly
public inline operator fun MutableCollection.plusAssign(elements: Sequence) {
this.addAll(elements)
}
/**
* Removes a single instance of the specified [element] from this mutable collection.
*/
@kotlin.internal.InlineOnly
public inline operator fun MutableCollection.minusAssign(element: T) {
this.remove(element)
}
/**
* Removes all elements contained in the given [elements] collection from this mutable collection.
*/
@kotlin.internal.InlineOnly
public inline operator fun MutableCollection.minusAssign(elements: Iterable) {
this.removeAll(elements)
}
/**
* Removes all elements contained in the given [elements] array from this mutable collection.
*/
@kotlin.internal.InlineOnly
public inline operator fun MutableCollection.minusAssign(elements: Array) {
this.removeAll(elements)
}
/**
* Removes all elements contained in the given [elements] sequence from this mutable collection.
*/
@kotlin.internal.InlineOnly
public inline operator fun MutableCollection.minusAssign(elements: Sequence) {
this.removeAll(elements)
}
/**
* Adds all elements of the given [elements] collection to this [MutableCollection].
*/
public fun MutableCollection.addAll(elements: Iterable): Boolean {
when (elements) {
is Collection -> return addAll(elements)
else -> {
var result: Boolean = false
for (item in elements)
if (add(item)) result = true
return result
}
}
}
/**
* Adds all elements of the given [elements] sequence to this [MutableCollection].
*/
public fun MutableCollection.addAll(elements: Sequence): Boolean {
var result: Boolean = false
for (item in elements) {
if (add(item)) result = true
}
return result
}
/**
* Adds all elements of the given [elements] array to this [MutableCollection].
*/
public fun MutableCollection.addAll(elements: Array): Boolean {
return addAll(elements.asList())
}
/**
* Converts this [Iterable] to a list if it is not a [Collection].
* Otherwise, returns this.
*/
internal fun Iterable.convertToListIfNotCollection(): Collection =
if (this is Collection) this else toList()
/**
* Removes all elements from this [MutableCollection] that are also contained in the given [elements] collection.
*/
public fun MutableCollection.removeAll(elements: Iterable): Boolean {
return removeAll(elements.convertToListIfNotCollection())
}
/**
* Removes all elements from this [MutableCollection] that are also contained in the given [elements] sequence.
*/
public fun MutableCollection.removeAll(elements: Sequence): Boolean {
val list = elements.toList()
return list.isNotEmpty() && removeAll(list)
}
/**
* Removes all elements from this [MutableCollection] that are also contained in the given [elements] array.
*/
public fun MutableCollection.removeAll(elements: Array): Boolean {
return elements.isNotEmpty() && removeAll(elements.asList())
}
/**
* Retains only elements of this [MutableCollection] that are contained in the given [elements] collection.
*/
public fun MutableCollection.retainAll(elements: Iterable): Boolean {
return retainAll(elements.convertToListIfNotCollection())
}
/**
* Retains only elements of this [MutableCollection] that are contained in the given [elements] array.
*/
public fun MutableCollection.retainAll(elements: Array): Boolean {
if (elements.isNotEmpty())
return retainAll(elements.asList())
else
return retainNothing()
}
/**
* Retains only elements of this [MutableCollection] that are contained in the given [elements] sequence.
*/
public fun MutableCollection.retainAll(elements: Sequence): Boolean {
val list = elements.toList()
if (list.isNotEmpty())
return retainAll(list)
else
return retainNothing()
}
private fun MutableCollection<*>.retainNothing(): Boolean {
val result = isNotEmpty()
clear()
return result
}
/**
* Removes all elements from this [MutableIterable] that match the given [predicate].
*
* @return `true` if any element was removed from this collection, or `false` when no elements were removed and collection was not modified.
*/
public fun MutableIterable.removeAll(predicate: (T) -> Boolean): Boolean = filterInPlace(predicate, true)
/**
* Retains only elements of this [MutableIterable] that match the given [predicate].
*
* @return `true` if any element was removed from this collection, or `false` when all elements were retained and collection was not modified.
*/
public fun MutableIterable.retainAll(predicate: (T) -> Boolean): Boolean = filterInPlace(predicate, false)
private fun MutableIterable.filterInPlace(predicate: (T) -> Boolean, predicateResultToRemove: Boolean): Boolean {
var result = false
with(iterator()) {
while (hasNext())
if (predicate(next()) == predicateResultToRemove) {
remove()
result = true
}
}
return result
}
/**
* Removes the element at the specified [index] from this list.
* In Kotlin one should use the [MutableList.removeAt] function instead.
*/
@Deprecated("Use removeAt(index) instead.", ReplaceWith("removeAt(index)"), level = DeprecationLevel.ERROR)
@kotlin.internal.InlineOnly
public inline fun MutableList.remove(index: Int): T = removeAt(index)
/**
* Removes the first element from this mutable list and returns that removed element, or throws [NoSuchElementException] if this list is empty.
*/
@SinceKotlin("1.4")
@WasExperimental(ExperimentalStdlibApi::class)
public fun MutableList.removeFirst(): T = if (isEmpty()) throw NoSuchElementException("List is empty.") else removeAt(0)
/**
* Removes the first element from this mutable list and returns that removed element, or returns `null` if this list is empty.
*/
@SinceKotlin("1.4")
@WasExperimental(ExperimentalStdlibApi::class)
public fun MutableList.removeFirstOrNull(): T? = if (isEmpty()) null else removeAt(0)
/**
* Removes the last element from this mutable list and returns that removed element, or throws [NoSuchElementException] if this list is empty.
*/
@SinceKotlin("1.4")
@WasExperimental(ExperimentalStdlibApi::class)
public fun MutableList.removeLast(): T = if (isEmpty()) throw NoSuchElementException("List is empty.") else removeAt(lastIndex)
/**
* Removes the last element from this mutable list and returns that removed element, or returns `null` if this list is empty.
*/
@SinceKotlin("1.4")
@WasExperimental(ExperimentalStdlibApi::class)
public fun MutableList.removeLastOrNull(): T? = if (isEmpty()) null else removeAt(lastIndex)
/**
* Removes all elements from this [MutableList] that match the given [predicate].
*
* @return `true` if any element was removed from this collection, or `false` when no elements were removed and collection was not modified.
*/
public fun MutableList.removeAll(predicate: (T) -> Boolean): Boolean = filterInPlace(predicate, true)
/**
* Retains only elements of this [MutableList] that match the given [predicate].
*
* @return `true` if any element was removed from this collection, or `false` when all elements were retained and collection was not modified.
*/
public fun MutableList.retainAll(predicate: (T) -> Boolean): Boolean = filterInPlace(predicate, false)
private fun MutableList.filterInPlace(predicate: (T) -> Boolean, predicateResultToRemove: Boolean): Boolean {
if (this !is RandomAccess)
return (this as MutableIterable).filterInPlace(predicate, predicateResultToRemove)
var writeIndex: Int = 0
for (readIndex in 0..lastIndex) {
val element = this[readIndex]
if (predicate(element) == predicateResultToRemove)
continue
if (writeIndex != readIndex)
this[writeIndex] = element
writeIndex++
}
if (writeIndex < size) {
for (removeIndex in lastIndex downTo writeIndex)
removeAt(removeIndex)
return true
} else {
return false
}
}