All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.jetbrains.kotlin.utils.SmartSet.kt Maven / Gradle / Ivy

There is a newer version: 2.1.0-RC
Show newest version
/*
 * 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() : AbstractSet() {
    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()
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy