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

commonMain.collections.OrderedSet.kt Maven / Gradle / Ivy

The newest version!
/**
 * Copyright (C) 2021 Dr. David H. Akehurst (http://dr.david.h.akehurst.net)
 *
 * 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 net.akehurst.language.agl.collections

interface OrderedSet : Set {
    operator fun get(index: Int): E
}

interface MutableOrderedSet : OrderedSet, MutableSet

fun  emptyOrderedSet(): OrderedSet = EmptyOrderedSet
fun  orderedSetOf(vararg elements: E): OrderedSet = OrderedSetImpl(elements.toList())
fun  mutableOrderedSetOf(vararg elements: E): MutableOrderedSet = MutableOrderedSetImpl(elements.toList())

fun  Iterable.toOrderedSet(): OrderedSet = when (this) {
    is Collection -> MutableOrderedSetImpl(this)
    else -> MutableOrderedSetImpl(this.toMutableSet())
}

fun  Iterable.toMutableOrderedSet(): MutableOrderedSet = when (this) {
    is Collection -> MutableOrderedSetImpl(this)
    else -> MutableOrderedSetImpl(this.toMutableSet())
}

operator fun  OrderedSet.plus(elements: Iterable): OrderedSet {
    //val result = OrderedSetImpl(mapCapacity(elements.collectionSizeOrNull()?.let { this.size + it } ?: this.size * 2))
    val result = this.toMutableList()
    result.addAll(elements)
    return OrderedSetImpl(result)
}

operator fun  MutableOrderedSet.plusAssign(elements: Iterable) {
    this.addAll(elements)
}

class OrderedSetImpl : OrderedSet {
    constructor() {
        this._impl = LinkedHashSet()
    }

    constructor(collection: Collection) {
        this._impl = LinkedHashSet(collection)
    }

    constructor(initialCapacity: Int) {
        this._impl = LinkedHashSet(initialCapacity)
    }

    private val _impl: LinkedHashSet

    override fun get(index: Int): E {
        _impl.forEachIndexed { i, e ->
            if (index == i) return e
        }
        throw IndexOutOfBoundsException("$index")
    }

    override val size: Int get() = _impl.size
    override fun iterator(): Iterator = _impl.iterator()
    override fun isEmpty(): Boolean = _impl.isEmpty()
    override fun contains(element: E): Boolean = _impl.contains(element)
    override fun containsAll(elements: Collection): Boolean = _impl.containsAll(elements)

    override fun equals(other: Any?): Boolean {
        return when {
            other !is OrderedSet<*> -> false
            other.size != this.size -> false
            else -> {
                for (i in 0..this.size) {
                    if (this[i] != other[i]) return false
                }
                true
            }
        }
    }

    override fun hashCode() = _impl.hashCode()
    override fun toString() = _impl.toString()
}

class MutableOrderedSetImpl : MutableOrderedSet {
    constructor() {
        this._impl = LinkedHashSet()
    }

    constructor(collection: Collection) {
        this._impl = LinkedHashSet(collection)
    }

    constructor(initialCapacity: Int) {
        this._impl = LinkedHashSet(initialCapacity)
    }

    private val _impl: LinkedHashSet

    override fun get(index: Int): E {
        _impl.forEachIndexed { i, e ->
            if (index == i) return e
        }
        throw IndexOutOfBoundsException("$index")
    }

    override val size: Int get() = _impl.size
    override fun iterator(): MutableIterator = _impl.iterator()
    override fun isEmpty(): Boolean = _impl.isEmpty()
    override fun contains(element: E): Boolean = _impl.contains(element)
    override fun containsAll(elements: Collection): Boolean = _impl.containsAll(elements)

    override fun add(element: E): Boolean = _impl.add(element)
    override fun addAll(elements: Collection): Boolean = _impl.addAll(elements)
    override fun remove(element: E): Boolean = _impl.remove(element)
    override fun removeAll(elements: Collection): Boolean = _impl.removeAll(elements)
    override fun retainAll(elements: Collection): Boolean = _impl.retainAll(elements)
    override fun clear() {
        _impl.clear()
    }

    override fun equals(other: Any?): Boolean {
        return when {
            other !is OrderedSet<*> -> false
            other.size != this.size -> false
            else -> {
                for (i in 0 until this.size) {
                    if (this[i] != other[i]) return false
                }
                true
            }
        }
    }

    override fun hashCode() = _impl.hashCode()
    override fun toString() = _impl.toString()
}

internal object EmptyIterator : ListIterator {
    override fun hasNext(): Boolean = false
    override fun hasPrevious(): Boolean = false
    override fun nextIndex(): Int = 0
    override fun previousIndex(): Int = -1
    override fun next(): Nothing = throw NoSuchElementException()
    override fun previous(): Nothing = throw NoSuchElementException()
}

internal object EmptyOrderedSet : OrderedSet {

    override val size: Int get() = 0
    override fun isEmpty(): Boolean = true
    override fun contains(element: Nothing): Boolean = false
    override fun containsAll(elements: Collection): Boolean = elements.isEmpty()

    override fun get(index: Int): Nothing = throw IndexOutOfBoundsException("An empty OrderedSet does not contain element at index $index.")
    override fun iterator(): Iterator = EmptyIterator

    override fun equals(other: Any?): Boolean = other is OrderedSet<*> && other.isEmpty()
    override fun hashCode(): Int = 0
    override fun toString(): String = "[]"
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy