kotlin.collections.Iterables.kt Maven / Gradle / Ivy
/*
* Copyright 2010-2016 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
@file:kotlin.jvm.JvmMultifileClass
@file:kotlin.jvm.JvmName("CollectionsKt")
package kotlin.collections
import java.util.*
/**
* Given an [iterator] function constructs an [Iterable] instance that returns values through the [Iterator]
* provided by that function.
*/
@kotlin.internal.InlineOnly
public inline fun Iterable(crossinline iterator: () -> Iterator): Iterable = object : Iterable {
override fun iterator(): Iterator = iterator()
}
/**
* A wrapper over another [Iterable] (or any other object that can produce an [Iterator]) that returns
* an indexing iterator.
*/
internal class IndexingIterable(private val iteratorFactory: () -> Iterator) : Iterable> {
override fun iterator(): Iterator> = IndexingIterator(iteratorFactory())
}
/**
* Returns the size of this iterable if it is known, or `null` otherwise.
*/
@kotlin.internal.InlineExposed
internal fun Iterable.collectionSizeOrNull(): Int? = if (this is Collection<*>) this.size else null
/**
* Returns the size of this iterable if it is known, or the specified [default] value otherwise.
*/
@kotlin.internal.InlineExposed
internal fun Iterable.collectionSizeOrDefault(default: Int): Int = if (this is Collection<*>) this.size else default
/** Returns true when it's safe to convert this collection to a set without changing contains method behavior. */
private fun Collection.safeToConvertToSet() = size > 2 && this is ArrayList
/** Converts this collection to a set, when it's worth so and it doesn't change contains method behavior. */
internal fun Iterable.convertToSetForSetOperationWith(source: Iterable): Collection =
when(this) {
is Set -> this
is Collection ->
when {
source is Collection && source.size < 2 -> this
else -> if (this.safeToConvertToSet()) toHashSet() else this
}
else -> toHashSet()
}
/** Converts this collection to a set, when it's worth so and it doesn't change contains method behavior. */
internal fun Iterable.convertToSetForSetOperation(): Collection =
when(this) {
is Set -> this
is Collection -> if (this.safeToConvertToSet()) toHashSet() else this
else -> toHashSet()
}
/**
* Returns a single list of all elements from all collections in the given collection.
*/
public fun Iterable>.flatten(): List {
val result = ArrayList()
for (element in this) {
result.addAll(element)
}
return result
}
/**
* Returns a pair of lists, where
* *first* list is built from the first values of each pair from this collection,
* *second* list is built from the second values of each pair from this collection.
*/
public fun Iterable>.unzip(): Pair, List> {
val expectedSize = collectionSizeOrDefault(10)
val listT = ArrayList(expectedSize)
val listR = ArrayList(expectedSize)
for (pair in this) {
listT.add(pair.first)
listR.add(pair.second)
}
return listT to listR
}