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

commonMain.implementations.persistentOrderedSet.PersistentOrderedSet.kt Maven / Gradle / Ivy

The newest version!
/*
 * Copyright 2016-2019 JetBrains s.r.o.
 * Use of this source code is governed by the Apache 2.0 License that can be found in the LICENSE.txt file.
 */

package kotlinx.collections.immutable.implementations.persistentOrderedSet

import kotlinx.collections.immutable.PersistentSet
import kotlinx.collections.immutable.implementations.immutableMap.PersistentHashMap
import kotlinx.collections.immutable.internal.EndOfChain
import kotlinx.collections.immutable.mutate

internal class Links(val previous: Any?, val next: Any?) {
    /** Constructs Links for a new single element */
    constructor() : this(EndOfChain, EndOfChain)
    /** Constructs Links for a new last element */
    constructor(previous: Any?) : this(previous, EndOfChain)

    fun withNext(newNext: Any?) = Links(previous, newNext)
    fun withPrevious(newPrevious: Any?) = Links(newPrevious, next)

    val hasNext get() = next !== EndOfChain
    val hasPrevious get() = previous !== EndOfChain
}

internal class PersistentOrderedSet(
        internal val firstElement: Any?,
        internal val lastElement: Any?,
        internal val hashMap: PersistentHashMap
) : AbstractSet(), PersistentSet {

    override val size: Int get() = hashMap.size

    override fun contains(element: E): Boolean = hashMap.containsKey(element)

    override fun add(element: E): PersistentSet {
        if (hashMap.containsKey(element)) {
            return this
        }
        if (isEmpty()) {
            val newMap = hashMap.put(element, Links())
            return PersistentOrderedSet(element, element, newMap)
        }
        @Suppress("UNCHECKED_CAST")
        val lastElement = lastElement as E
        val lastLinks = hashMap[lastElement]!!
//        assert(!lastLinks.hasNext)

        val newMap = hashMap
                .put(lastElement, lastLinks.withNext(element))
                .put(element, Links(previous = lastElement))
        return PersistentOrderedSet(firstElement, element, newMap)
    }

    override fun addAll(elements: Collection): PersistentSet {
        if (elements.isEmpty()) return this
        return this.mutate { it.addAll(elements) }
    }

    override fun remove(element: E): PersistentSet {
        val links = hashMap[element] ?: return this

        var newMap = hashMap.remove(element)
        if (links.hasPrevious) {
            val previousLinks = newMap[links.previous]!!
//            assert(previousLinks.next == element)
            @Suppress("UNCHECKED_CAST")
            newMap = newMap.put(links.previous as E, previousLinks.withNext(links.next))
        }
        if (links.hasNext) {
            val nextLinks = newMap[links.next]!!
//            assert(nextLinks.previous == element)
            @Suppress("UNCHECKED_CAST")
            newMap = newMap.put(links.next as E, nextLinks.withPrevious(links.previous))
        }
        val newFirstElement = if (!links.hasPrevious) links.next else firstElement
        val newLastElement = if (!links.hasNext) links.previous else lastElement
        return PersistentOrderedSet(newFirstElement, newLastElement, newMap)
    }

    override fun removeAll(elements: Collection): PersistentSet {
        if (elements.isEmpty()) return this
        return mutate { it.removeAll(elements) }
    }

    override fun removeAll(predicate: (E) -> Boolean): PersistentSet {
        return mutate { it.removeAll(predicate) }
    }

    override fun retainAll(elements: Collection): PersistentSet {
        if (elements.isEmpty()) return PersistentOrderedSet.emptyOf()
        return mutate { it.retainAll(elements) }
    }

    override fun clear(): PersistentSet {
        return PersistentOrderedSet.emptyOf()
    }

    override fun iterator(): Iterator {
        return PersistentOrderedSetIterator(firstElement, hashMap)
    }

    override fun builder(): PersistentSet.Builder {
        return PersistentOrderedSetBuilder(this)
    }

    override fun equals(other: Any?): Boolean {
        if (other === this) return true
        if (other !is Set<*>) return false
        if (size != other.size) return false

        return when (other) {
            is PersistentOrderedSet<*> -> {
                hashMap.node.equalsWith(other.hashMap.node) { _, _ -> true }
            }
            is PersistentOrderedSetBuilder<*> -> {
                hashMap.node.equalsWith(other.hashMapBuilder.node) { _, _ -> true }
            }
            else -> super.equals(other)
        }
    }

    /**
     * We provide [equals], so as a matter of style, we should also provide [hashCode].
     * However, the implementation from [AbstractSet] is enough.
     */
    override fun hashCode(): Int = super.hashCode()

    internal companion object {
        private val EMPTY = PersistentOrderedSet(EndOfChain, EndOfChain, PersistentHashMap.emptyOf())
        internal fun  emptyOf(): PersistentSet = EMPTY
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy