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

scala.collection.mutable.ExtHashSet.scala Maven / Gradle / Ivy

The newest version!
package scala.collection
package mutable

import scala.util.Random
import scala.collection.generic.{GenericSetTemplate, MutableSetFactory}

/* Alternatively we could use `hashTableContents` as suggested by Rüdiger Klaehn like

package scala.collection.mutable
object HashSetExt {
  implicit class HashSetDraw[A](val value: HashSet[A]) extends AnyVal {
    def draw(random:Random) : A = {
      val table = value.hashTableContents.table
      ...
 */
class ExtHashSet[A]
    extends HashSet[A]
    with SetLike[A, ExtHashSet[A]]
    with GenericSetTemplate[A, ExtHashSet]
    with ExtSetMethods[A] {
  def empty[A]: Set[A]   = new ExtHashSet[A]
  override def companion = ExtHashSet

  def draw(random: Random): A = {
    val len   = table.length
    val drawn = random.nextInt(len) // IllegalArgumentException if len == 0
    def search(from: Int, incr: Int, hold: Int => Boolean): Option[A] = {
      var i = from
      while (hold(i)) {
        val elem = table(i)
        if (elem ne null) return Some(elem.asInstanceOf[A])
        else i += incr
      }
      None
    }
    // must always find an element either upwards or downwards
    search(drawn, 1, (i: Int) => i < len) getOrElse (search(drawn - 1, -1, (i: Int) => i > 0).get)
  }

  override def findElem(elem: A): Option[A] = findEntry(elem)

  def findElem[B](other: B, correspond: (A, B) => Boolean): A = {
    var entry: AnyRef = null
    if (null != other) {
      var h = index(other.hashCode)
      entry = table(h)
      while (null != entry && !correspond(entry.asInstanceOf[A], other)) {
        h = (h + 1) % table.length
        entry = table(h)
      }
    }
    entry.asInstanceOf[A]
  }

  /** Returns an `Iterator` over all entries having the passed `hashCode`.
    */
  def hashCodeIterator(hcode: Int): Iterator[A] = new AbstractIterator[A] {
    private var h     = index(hcode)
    private var entry = table(h)

    def hasNext = null != entry && entry.hashCode == hcode
    def next = {
      val prevEntry = entry
      h = (h + 1) % table.length
      entry = table(h)
      prevEntry.asInstanceOf[A]
    }
  }

  /** Updates or inserts `elem`.
    *  @return `true` if an update took place.
    */
  def upsert(elem: A with AnyRef): Boolean = {
    var h     = index(elem.##)
    var entry = table(h)
    while (null != entry) {
      if (entry == elem) {
        table(h) = elem
        return false
      }
      h = (h + 1) % table.length
      entry = table(h)
    }
    addEntry(elem)
  }
}

object ExtHashSet extends MutableSetFactory[ExtHashSet] {
  override def empty[A]      = new ExtHashSet[A]
  override def newBuilder[A] = new GrowingBuilder[A, ExtHashSet[A]](empty[A])

  def fill[A](n: Int)(elem: => A): ExtHashSet[A] = {
    val b = newBuilder[A]
    for (i <- 0 to n)
      b += elem
    b.result()
  }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy