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

org.opalj.collection.LongIterator.scala Maven / Gradle / Ivy

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

import java.util.function.LongPredicate
import java.util.function.LongConsumer

import scala.collection.AbstractIterator
import org.opalj.collection.immutable.LongTrieSet

/**
 * Iterator over a collection of longs; basically all methods are overridden to avoid
 * (un)boxing operations.
 *
 * @author Michael Eichberg
 */
abstract class LongIterator extends AbstractIterator[Long] { self ⇒

    def ++(other: LongIterator): LongIterator = {
        new LongIterator {
            private[this] var it = self
            override def hasNext = it != null
            override def next: Long = {
                val v = it.next
                if (!it.hasNext) {
                    it = if (it eq self) other else null
                }
                v
            }
        }
    }

    /**
     * Returns the next value if `hasNext` has returned `true`; if hasNext has returned `false`
     * and `next` is called, the result is undefined. The method may throw an
     * `UnsupportedOperationException` or just return the last value; however, the behavior
     * is undefined and subject to change without notice!
     */
    def next(): Long

    override def exists(p: Long ⇒ Boolean): Boolean = {
        while (this.hasNext) { if (p(this.next())) return true; }
        false
    }
    override def forall(p: Long ⇒ Boolean): Boolean = {
        while (this.hasNext) { if (!p(this.next())) return false; }
        true
    }
    def contains(i: Long): Boolean = {
        while (this.hasNext) { if (i == this.next()) return true; }
        false
    }
    override def foldLeft[B](start: B)(f: (B, Long) ⇒ B): B = {
        var c = start
        while (this.hasNext) { c = f(c, next()) }
        c
    }

    def foreachWhile(p: LongPredicate)(f: LongConsumer): Unit = {
        while (this.hasNext && {
            val c = this.next()
            if (p.test(c)) {
                f.accept(c)
                true
            } else {
                false
            }
        }) { /*empty*/ }
    }

    def map(f: Long ⇒ Long): LongIterator = {
        new LongIterator {
            def hasNext: Boolean = self.hasNext
            def next(): Long = f(self.next())
        }
    }

    override def take(n: Int): LongIterator = {
        new LongIterator {
            private[this] var i: Int = 0
            def hasNext: Boolean = self.hasNext && i < n
            def next(): Long = { i += 1; self.next() }
        }
    }

    def map(f: Long ⇒ Int): IntIterator = new IntIterator {
        def hasNext: Boolean = self.hasNext
        def next(): Int = f(self.next())
    }
    override def map[X](m: Long ⇒ X): RefIterator[X] = new RefIterator[X] {
        def hasNext: Boolean = self.hasNext
        def next: X = m(self.next())
    }

    override def foreach[U](f: Long ⇒ U): Unit = while (hasNext) f(next())

    def flatMap(f: Long ⇒ LongIterator): LongIterator = {
        new LongIterator {
            private[this] var it: LongIterator = LongIterator.empty
            private[this] def advanceIterator(): Unit = {
                while (!it.hasNext) {
                    if (self.hasNext) {
                        it = f(self.next())
                    } else {
                        it = null
                        return ;
                    }
                }
            }
            advanceIterator()
            def hasNext: Boolean = it != null
            def next(): Long = { val e = it.next(); advanceIterator(); e }
        }
    }

    override def withFilter(p: Long ⇒ Boolean): LongIterator = filter(p)

    override def filter(p: Long ⇒ Boolean): LongIterator = new LongIterator {
        private[this] var hasNextValue: Boolean = true
        private[this] var v: Long = 0
        private[this] def goToNextValue(): Unit = {
            while (self.hasNext) {
                v = self.next()
                if (p(v)) return ;
            }
            hasNextValue = false
        }

        goToNextValue()

        def hasNext: Boolean = hasNextValue
        def next(): Long = { val v = this.v; goToNextValue(); v }
    }

    def toArray: Array[Long] = {
        var asLength = 8
        var as = new Array[Long](asLength)

        var i = 0
        while (hasNext) {
            if (i == asLength) {
                val newAS = new Array[Long](Math.min(asLength * 2, asLength + 512))
                Array.copy(as, 0, newAS, 0, asLength)
                as = newAS
                asLength = as.length
            }
            val v = next()
            as(i) = v
            i += 1
        }
        if (i == asLength)
            as
        else {
            val resultAs = new Array[Long](i)
            Array.copy(as, 0, resultAs, 0, i)
            resultAs
        }
    }

    def toSet: LongSet = {
        var s = LongTrieSet.empty
        while (hasNext) { s += next() }
        s
    }

    /**
     * Copies all elements to a target array of the given size. The size has to be
     * at least the size of elements of this iterator.
     */
    private[opalj] def toArray(size: Int): Array[Long] = {
        val as = new Array[Long](size)
        var i = 0
        while (hasNext) {
            val v = next()
            as(i) = v
            i += 1
        }
        as
    }

    /**
     * Compares the returned values to check if the iteration order is the same.
     *
     * Both iterators may be consumed up to an arbitrary point.
     */
    def sameValues(that: LongIterator): Boolean = {
        while (this.hasNext) {
            if (!that.hasNext || this.next() != that.next())
                return false;
        }
        !that.hasNext
    }

}

object LongIterator {

    final val empty: LongIterator = new LongIterator {
        def hasNext: Boolean = false
        def next(): Nothing = throw new UnsupportedOperationException
        override def toArray: Array[Long] = new Array[Long](0)
        override def toSet: LongTrieSet = LongTrieSet.empty
    }

    def apply(i: Long): LongIterator = new LongIterator {
        private[this] var returned = false
        def hasNext: Boolean = !returned
        def next(): Long = { returned = true; i }
        override def toArray: Array[Long] = { val as = new Array[Long](1); as(0) = i; as }
        override def toSet: LongTrieSet = LongTrieSet(i)
    }

    def apply(i1: Long, i2: Long): LongIterator = new LongIterator {
        private[this] var nextId: Int = 0
        def hasNext: Boolean = nextId < 2
        def next(): Long = { if (nextId == 0) { nextId = 1; i1 } else { nextId = 2; i2 } }
        override def toArray: Array[Long] = {
            val as = new Array[Long](2)
            as(0) = i1
            as(1) = i2
            as
        }
        override def toSet: LongTrieSet = LongTrieSet(i1, i2)
    }

    def apply(i1: Long, i2: Long, i3: Long): LongIterator = new LongIterator {
        private[this] var nextId: Int = 0
        def hasNext: Boolean = nextId < 3
        def next(): Long = { nextId += 1; if (nextId == 1) i1 else if (nextId == 2) i2 else i3 }
        override def toArray: Array[Long] = {
            val as = new Array[Long](3)
            as(0) = i1
            as(1) = i2
            as(2) = i3
            as
        }
        override def toSet: LongTrieSet = LongTrieSet(i1, i2, i3)
    }

    def apply(i1: Long, i2: Long, i3: Long, i4: Long): LongIterator = new LongIterator {
        private[this] var nextId: Int = 0
        def hasNext: Boolean = nextId < 4
        def next(): Long = {
            nextId += 1
            nextId match {
                case 1 ⇒ i1
                case 2 ⇒ i2
                case 3 ⇒ i3
                case _ ⇒ i4
            }
        }
        override def toArray: Array[Long] = {
            val as = new Array[Long](3)
            as(0) = i1
            as(1) = i2
            as(2) = i3
            as(3) = i4
            as
        }
        override def toSet: LongTrieSet = LongTrieSet(i1, i2, i3, i4)
    }

}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy