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

org.opalj.collection.immutable.Int2List.scala Maven / Gradle / Ivy

The newest version!
/* BSD 2-Clause License - see OPAL/LICENSE for details. */
package org.opalj
package collection
package immutable

/**
 * A growable, immutable linked list based data store for '''int values''' except `Int.MinValue`.
 * Though this data store is backed by a linked list, it is not a classical linked list and it
 * does not offer (efficient) head and tail operations. However, compared to a classical linked
 * list the memory usage is reduced by ~33% and a simple foreach is also ~17% faster, the time
 * to create the list is comparable and iteration using an Iterator is marginally slower if at all.
 * The basic idea is to two store 2 values in each node of the linked list to reduce the overhead
 * incurred by the creation of the objects.
 *
 * This list does not perform any length related checks. I.e., it fails,e.g., in
 * case of `forFirstN` if the size of the list is smaller than expected.
 *
 * Furthermore, all directly implemented methods use `while` loops for maximum
 * efficiency and the list is also specialized for primitive `int` values which
 * makes this list far more efficient when used for storing lists of `int` values.
 *
 * @author Michael Eichberg
 */
sealed trait Int2List extends Serializable { self ⇒

    private[immutable] def h: Int
    private[immutable] def t: Int
    private[immutable] def rest: Int2List

    def isEmpty: Boolean
    def isSingletonList: Boolean
    def nonEmpty: Boolean

    def foreach[U](f: Int ⇒ U): Unit

    /** Iterates over the first N values. */
    def forFirstN[U](n: Int)(f: Int ⇒ U): Unit

    /**
     * @return An iterator over this list's values. In general, you should prefer using foreach or
     *         the other specialized methods to avoid the overhead incurred by the generation of
     *         the iterator.
     */
    def iterator: IntIterator

    /** Prepends the given value to this list. E.g., `l = 2 +: l`. */
    def +:(v: Int): Int2List

    final override def equals(other: Any): Boolean = {
        other match {
            case l: Int2List ⇒ equals(l)
            case _           ⇒ false
        }
    }
    def equals(that: Int2List): Boolean

    override def hashCode(): Int // just added to ensure that we have to override hashCode!
}

object Int2List {

    def empty: Int2List = Int2ListEnd

    def apply(v: Int): Int2List = new Int2ListNode(Int.MinValue, v, Int2ListEnd)

    def apply(head: Int, last: Int): Int2List = new Int2ListNode(head, last, Int2ListEnd)

}

/**
 * An empty [[Int2List]].
 *
 * @author Michael Eichberg
 */
case object Int2ListEnd extends Int2List {

    override def isEmpty: Boolean = true
    override def isSingletonList: Boolean = false
    override def nonEmpty: Boolean = false

    override private[immutable] def h: Int = throw new UnsupportedOperationException
    override private[immutable] def t: Int = throw new UnsupportedOperationException
    override private[immutable] def rest: Int2List = throw new UnsupportedOperationException

    override def foreach[U](f: Int ⇒ U): Unit = {}
    /** Iterates over the first N values. */
    override def forFirstN[U](n: Int)(f: Int ⇒ U): Unit = {}
    override def iterator: IntIterator = IntIterator.empty
    /** Prepends the given value to this list. E.g., `l = 2l +: l`. */
    override def +:(v: Int): Int2List = new Int2ListNode(Int.MinValue, v, this)

    override def equals(that: Int2List): Boolean = this eq that
    override def hashCode(): Int = 37
}

/**
 * An container for a list element.
 *
 * @author Michael Eichberg
 */
final case class Int2ListNode(
        private[immutable] var h:    Int,
        private[immutable] var t:    Int,
        private[immutable] var rest: Int2List = Int2ListEnd
) extends Int2List { list ⇒

    override def isEmpty: Boolean = false
    override def isSingletonList: Boolean = h == Int.MinValue && (rest eq Int2ListEnd)
    override def nonEmpty: Boolean = true

    override def foreach[U](f: Int ⇒ U): Unit = {
        if (h != Int.MinValue) f(h)
        f(t)
        var list: Int2List = this.rest
        while (list.nonEmpty) {
            f(list.h)
            f(list.t)
            list = list.rest
        }
    }

    override def forFirstN[U](n: Int)(f: Int ⇒ U): Unit = {
        n match {
            case 0 ⇒
                return ;
            case 1 ⇒
                if (h != Int.MinValue)
                    f(h)
                else
                    f(t)
                return ;
            case _ ⇒
                // ... n >= 2
                var i = n - 1 // <= for the second element...
                if (h != Int.MinValue) { f(h); i -= 1 }
                f(t)
                var list: Int2List = rest
                while (i > 0) {
                    i -= 2
                    f(list.h)
                    if (i >= 0) f(list.t)
                    list = list.rest
                }
        }
    }

    override def iterator: IntIterator = {
        new IntIterator {
            private[this] var currentList: Int2List = list
            private[this] var head: Boolean = list.h != Int.MinValue
            def hasNext: Boolean = currentList ne Int2ListEnd
            def next: Int = {
                if (head) {
                    head = false
                    currentList.h
                } else {
                    head = true
                    val v = currentList.t
                    currentList = currentList.rest
                    v
                }
            }
        }
    }

    override def +:(v: Int): Int2List = {
        if (h != Int.MinValue)
            new Int2ListNode(Int.MinValue, v, this)
        else
            new Int2ListNode(v, t, this.rest)
    }

    override def equals(that: Int2List): Boolean = {
        (that eq this) || {
            var thisList: Int2List = this
            var thatList = that
            while ((thisList ne Int2ListEnd) && (thatList ne Int2ListEnd)) {
                if (thisList.h != thatList.h || thisList.t != thatList.t)
                    return false;
                thisList = thisList.rest
                thatList = thatList.rest
            }
            thisList eq thatList //... <=> true iff both lists are empty
        }
    }

    override def hashCode(): Int = {
        var h = 31
        var list: Int2List = this
        while (list ne Int2ListEnd) {
            h = ((h + list.h) * 31 + (list.t)) * 31
            list = list.rest
        }
        h
    }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy