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

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

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

import java.lang.{Long ⇒ JLong}

/**
 * An immutable linked list for storing long values.
 * 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.
 *
 * @note    In most cases a `LongList` can be used as a drop-in replacement for a standard
 *          Scala List.
 *
 * @author Michael Eichberg
 */
sealed trait LongList extends Serializable { self ⇒

    def isEmpty: Boolean
    def nonEmpty: Boolean

    def head: Long
    def tail: LongList

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

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

    def iterator: LongIterator

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

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

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

object LongList {

    def empty: LongList = LongList0

    def apply(v: Long): LongList = new LongListNode(v, LongList0)

    def apply(head: Long, last: Long): LongList = {
        new LongListNode(head, new LongListNode(last, LongList0))
    }

}

/**
 * An empty [[LongList]].
 *
 * @author Michael Eichberg
 */
case object LongList0 extends LongList {
    override def head: Long = throw new UnsupportedOperationException
    override def tail: LongList = throw new UnsupportedOperationException
    override def isEmpty: Boolean = true
    override def nonEmpty: Boolean = false

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

    override def equals(that: LongList): Boolean = that eq this
    override def hashCode(): Int = 31
}

/**
 * An container for a list element.
 *
 * @author Michael Eichberg
 */
final case class LongListNode(
        head:                        Long,
        private[immutable] var rest: LongList = LongList0
) extends LongList { list ⇒

    override def tail: LongList = rest

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

    override def foreach[U](f: Long ⇒ U): Unit = {
        var list: LongList = this
        do {
            f(list.head)
            list = list.tail
        } while (list.nonEmpty)
    }

    override def forFirstN[U](n: Int)(f: Long ⇒ U): Unit = {
        if (n == 0) return ;

        var i = 0
        var list: LongList = this
        do {
            f(list.head)
            list = list.tail
            i += 1
        } while (list.nonEmpty && i < n)
    }

    override def iterator: LongIterator = {
        new LongIterator {
            private[this] var currentList: LongList = list
            def hasNext: Boolean = currentList.nonEmpty
            def next: Long = {
                val v = currentList.head
                currentList = currentList.tail
                v
            }
        }
    }

    override def +:(v: Long): LongList = new LongListNode(v, this)

    override def equals(that: LongList): Boolean = {
        (that eq this) || {
            var thisList: LongList = this
            var thatList = that
            while ((thisList ne LongList0) && (thatList ne LongList0)) {
                if (thisList.head != thatList.head)
                    return false;
                thisList = thisList.tail
                thatList = thatList.tail
            }
            thisList eq thatList //... <=> true iff both lists are empty
        }
    }

    override def hashCode(): Int = {
        var h = 31
        var list: LongList = this
        while (list ne LongList0) {
            h = (h + JLong.hashCode(list.head)) * 31
            list = list.tail
        }
        h
    }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy