org.jetbrains.kotlin.utils.SmartSet.kt Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of kotlin-compiler-embeddable Show documentation
Show all versions of kotlin-compiler-embeddable Show documentation
the Kotlin compiler embeddable
/*
* Copyright 2010-2015 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.
*/
package org.jetbrains.kotlin.utils
import java.util.*
/**
* A set which is optimized for small sizes and maintains the order in which the elements were added.
* This set is not synchronized and it does not support removal operations such as [MutableSet.remove],
* [MutableSet.removeAll] and [MutableSet.retainAll].
* Also, [iterator] returns an iterator which does not support [MutableIterator.remove].
*/
@Suppress("UNCHECKED_CAST")
class SmartSet private constructor() : AbstractMutableSet() {
companion object {
private const val ARRAY_THRESHOLD = 5
@JvmStatic
fun create() = SmartSet()
@JvmStatic
fun create(set: Collection) = SmartSet().apply { this.addAll(set) }
}
// null if size = 0, object if size = 1, array of objects if size < threshold, linked hash set otherwise
private var data: Any? = null
override var size: Int = 0
override fun iterator(): MutableIterator = when {
size == 0 -> Collections.emptySet().iterator()
size == 1 -> SingletonIterator(data as T)
size < ARRAY_THRESHOLD -> ArrayIterator(data as Array)
else -> (data as MutableSet).iterator()
}
override fun add(element: T): Boolean {
when {
size == 0 -> {
data = element
}
size == 1 -> {
if (data == element) return false
data = arrayOf(data, element)
}
size < ARRAY_THRESHOLD -> {
val arr = data as Array
if (element in arr) return false
data = if (size == ARRAY_THRESHOLD - 1) linkedSetOf(*arr).apply { add(element) }
else arr.copyOf(size + 1).apply { set(size - 1, element) }
}
else -> {
val set = data as MutableSet
if (!set.add(element)) return false
}
}
size++
return true
}
override fun clear() {
data = null
size = 0
}
override fun contains(element: T): Boolean = when {
size == 0 -> false
size == 1 -> data == element
size < ARRAY_THRESHOLD -> element in data as Array
else -> element in data as Set
}
private class SingletonIterator(private val element: T) : MutableIterator {
private var hasNext = true
override fun next(): T =
if (hasNext) {
hasNext = false
element
} else throw NoSuchElementException()
override fun hasNext() = hasNext
override fun remove() = throw UnsupportedOperationException()
}
private class ArrayIterator(array: Array) : MutableIterator {
private val arrayIterator = array.iterator()
override fun hasNext(): Boolean = arrayIterator.hasNext()
override fun next(): T = arrayIterator.next()
override fun remove() = throw UnsupportedOperationException()
}
}