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

commonMain.implementations.immutableMap.PersistentHashMap.kt Maven / Gradle / Ivy

There is a newer version: 0.3.8
Show 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.immutableMap

import kotlinx.collections.immutable.ImmutableCollection
import kotlinx.collections.immutable.ImmutableSet
import kotlinx.collections.immutable.PersistentMap
import kotlinx.collections.immutable.implementations.persistentOrderedMap.PersistentOrderedMap
import kotlinx.collections.immutable.implementations.persistentOrderedMap.PersistentOrderedMapBuilder
import kotlinx.collections.immutable.mutate

internal class PersistentHashMap(internal val node: TrieNode,
                                       override val size: Int): AbstractMap(), PersistentMap {

    override val keys: ImmutableSet
        get() {
            return PersistentHashMapKeys(this)
        }

    override val values: ImmutableCollection
        get() {
            return PersistentHashMapValues(this)
        }

    override val entries: ImmutableSet>
        get() {
            return createEntries()
        }

    private fun createEntries(): ImmutableSet> {
        return PersistentHashMapEntries(this)
    }

    // TODO: compiler bug: this bridge should be generated automatically
    @PublishedApi
    internal fun getEntries(): Set> {
        return createEntries()
    }

    override fun containsKey(key: K): Boolean {
        return node.containsKey(key.hashCode(), key, 0)
    }

    override fun get(key: K): V? {
        return node.get(key.hashCode(), key, 0)
    }

    override fun put(key: K, value: @UnsafeVariance V): PersistentHashMap {
        val newNodeResult = node.put(key.hashCode(), key, value, 0) ?: return this
        return PersistentHashMap(newNodeResult.node, size + newNodeResult.sizeDelta)
    }

    override fun remove(key: K): PersistentHashMap {
        val newNode = node.remove(key.hashCode(), key, 0)
        if (node === newNode) { return this }
        if (newNode == null) { return emptyOf() }
        return PersistentHashMap(newNode, size - 1)
    }

    override fun remove(key: K, value: @UnsafeVariance V): PersistentHashMap {
        val newNode = node.remove(key.hashCode(), key, value, 0)
        if (node === newNode) { return this }
        if (newNode == null) { return emptyOf() }
        return PersistentHashMap(newNode, size - 1)
    }

    override fun putAll(m: Map): PersistentMap {
        return this.mutate { it.putAll(m) }
    }

    override fun clear(): PersistentMap {
        return PersistentHashMap.emptyOf()
    }

    override fun builder(): PersistentHashMapBuilder {
        return PersistentHashMapBuilder(this)
    }

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

        return when (other) {
            is PersistentOrderedMap<*, *> -> {
                node.equalsWith(other.hashMap.node) { a, b ->
                    a == b.value
                }
            }
            is PersistentOrderedMapBuilder<*, *> -> {
                node.equalsWith(other.hashMapBuilder.node) { a, b ->
                    a == b.value
                }
            }
            is PersistentHashMap<*, *> -> {
                node.equalsWith(other.node) { a, b -> a == b }
            }
            is PersistentHashMapBuilder<*, *> -> {
                node.equalsWith(other.node) { a, b -> a == b }
            }
            else -> super.equals(other)
        }
    }

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

    internal companion object {
        private val EMPTY = PersistentHashMap(TrieNode.EMPTY, 0)
        @Suppress("UNCHECKED_CAST")
        internal fun  emptyOf(): PersistentHashMap = EMPTY as PersistentHashMap
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy