listbuffer.scala

来自「JAVA 语言的函数式编程扩展」· SCALA 代码 · 共 306 行

SCALA
306
字号
/*                     __                                               *\**     ________ ___   / /  ___     Scala API                            ****    / __/ __// _ | / /  / _ |    (c) 2003-2007, LAMP/EPFL             ****  __\ \/ /__/ __ |/ /__/ __ |    http://scala-lang.org/               **** /____/\___/_/ |_/____/_/ | |                                         ****                          |/                                          **\*                                                                      */// $Id: ListBuffer.scala 14378 2008-03-13 11:39:05Z dragos $package scala.collection.mutableimport Predef._/** A Buffer implementation back up by a list. It provides constant time *  prepend and append. Most other operations are linear. * *  @author  Matthias Zenger *  @version 1.0, 15/03/2004 */@serializablefinal class ListBuffer[A] extends Buffer[A] {  private var start: List[A] = Nil  private var last0: ::[A] = _  private var exported: Boolean = false  /** Prepends a single element to this buffer. It takes constant   *  time.   *   *  @param x  the element to prepend.   *  @return   this buffer.   */  def +: (x: A): Buffer[A] = {    if (exported) copy()    val newElem = new scala.:: (x, start)    if (start.isEmpty) last0 = newElem    start = newElem    this  }      /** Appends a single element to this buffer. It takes constant   *  time.   *   *  @param x  the element to append.   */  override def += (x: A) {    if (exported) copy()    if (start.isEmpty) {      last0 = new scala.:: (x, Nil)      start = last0    } else {      val last1 = last0      last0 = new scala.:: (x, Nil)      last1.tl = last0    }  }  /** Removes a single element from the buffer and return   *  the identity of the buffer. Same as <code>this -= x; this</code>. It   *  takes linear time (except removing the first element, which is done    *  in constant time).   *   *  @param x  the element to remove.   *  @return   this buffer.   */  def - (x: A): Buffer[A] = { this -= x; this }  /** Remove a single element from this buffer. It takes linear time   *  (except removing the first element, which is done  in constant time).   *   *  @param x  the element to remove.   */  override def -= (x: A) {    if (exported) copy()    if (start.isEmpty) {}    else if (start.head == x) start = start.tail    else {      var cursor = start      while (!cursor.tail.isEmpty && cursor.tail.head != x) { cursor = cursor.tail }      if (!cursor.tail.isEmpty) {        val z = cursor.asInstanceOf[scala.::[A]]        if (z.tl == last0)          last0 = z        z.tl = cursor.tail.tail      }    }  }  /** Converts this buffer to a list. Takes constant time. The buffer is    *  copied lazily, the first time it is mutated.   */  override def toList: List[A] = {    exported = !start.isEmpty    start  }  /** expose the underlying list but do not mark it as exported */  override def readOnly : List[A] = start  /** Prepends the elements of this buffer to a given list   *   *  @param xs   the list to which elements are prepended   */  def prependToList(xs: List[A]): List[A] =    if (start.isEmpty) xs    else { last0.tl = xs; toList }  /** Clears the buffer contents.   */  def clear() {    start = Nil    exported = false  }  /** Copy contents of this buffer */  private def copy() {    var cursor = start    val limit = last0.tail    clear    while (cursor ne limit) {      this += cursor.head      cursor = cursor.tail    }  }  /** Returns the length of this buffer. It takes linear time.   *   *  @return the length of this buffer.   */  def length: Int = start.length    // will be faster since this is a list  override def isEmpty = start.isEmpty  /** Returns the n-th element of this list. This method   *  yields an error if the element does not exist. Takes time   *  linear in the buffer size.   *   *  @param n  the position of the element to be returned.   *  @return   the n-th element of this buffer.   *  @throws Predef.IndexOutOfBoundsException   */  def apply(n: Int): A = try {    start(n)  } catch {    case ex: Exception =>      throw new IndexOutOfBoundsException(n.toString())  }  /** Replaces element at index <code>n</code> with the new element   *  <code>newelem</code>. Takes time linear in the buffer size. (except the first   *  element, which is updated in constant time).   *   *  @param n  the index of the element to replace.   *  @param x  the new element.   *  @throws Predef.IndexOutOfBoundsException if <code>n</code> is out of bounds.   */  def update(n: Int, x: A) {    try {      if (exported) copy()      if (n == 0) {        val newElem = new scala.:: (x, start.tail);        if (last0 eq start) last0 = newElem        start = newElem      } else {        var cursor = start        var i = 1        while (i < n) {          cursor = cursor.tail          i += 1        }        val newElem = new scala.:: (x, cursor.tail.tail)        if (last0 eq cursor.tail) last0 = newElem        cursor.asInstanceOf[scala.::[A]].tl = newElem      }    } catch {      case ex: Exception => throw new IndexOutOfBoundsException(n.toString())    }  }  /** Inserts new elements at the index <code>n</code>. Opposed to method   *  <code>update</code>, this method will not replace an element with a new   *  one. Instead, it will insert a new element at index <code>n</code>.   *   *  @param  n     the index where a new element will be inserted.   *  @param  iter  the iterable object providing all elements to insert.   *  @throws Predef.IndexOutOfBoundsException if <code>n</code> is out of bounds.   */  def insertAll(n: Int, iter: Iterable[A]) {    try {      if (exported) copy()      var elems = iter.elements.toList.reverse      if (n == 0) {        while (!elems.isEmpty) {          val newElem = new scala.:: (elems.head, start)          if (start.isEmpty) last0 = newElem          start = newElem          elems = elems.tail        }      } else {        var cursor = start        var i = 1        while (i < n) {          cursor = cursor.tail          i += 1        }        while (!elems.isEmpty) {          val newElem = new scala.:: (elems.head, cursor.tail)          if (cursor.tail.isEmpty) last0 = newElem          cursor.asInstanceOf[scala.::[A]].tl = newElem          elems = elems.tail        }      }    } catch {      case ex: Exception =>        throw new IndexOutOfBoundsException(n.toString())    }  }  /** Removes the element on a given index position. Takes time linear in   *  the buffer size (except for the first element, which is removed in constant   *  time).   *   *  @param  n  the index which refers to the element to delete.   *  @return n  the element that was formerly at position <code>n</code>.   *  @pre       an element exists at position <code>n</code>   *  @throws Predef.IndexOutOfBoundsException if <code>n</code> is out of bounds.   */  def remove(n: Int): A = try {    if (exported) copy()    var old = start.head;    if (n == 0) {      start = start.tail    } else {      var cursor = start      var i = 1      while (i < n) {        cursor = cursor.tail        i += 1      }      old = cursor.tail.head      if (last0 eq cursor.tail) last0 = cursor.asInstanceOf[scala.::[A]]      cursor.asInstanceOf[scala.::[A]].tl = cursor.tail.tail    }    old  } catch {    case ex: Exception =>      throw new IndexOutOfBoundsException(n.toString())  }  /** <p>   *    Returns an iterator over all elements of this list.   *  </p>   *  <blockquote>   *    Note: the iterator can be affected by insertions, updates and   *    deletions that are performed afterwards on the buffer. To get   *    iterator an over the current buffer snapshot, use   *    <code>toList.elements</code>.   *  </blockquote>   *   *  @throws Predef.NoSuchElementException if buffer is empty   */  override def elements = new Iterator[A] {    var cursor: List[A] = null    def hasNext: Boolean = !start.isEmpty && cursor != last0    def next(): A =      if (!hasNext) {        throw new NoSuchElementException("next on empty Iterator")      } else {        if (cursor eq null) cursor = start else cursor = cursor.tail        cursor.head      }  }  /** Returns a clone of this buffer.   *   *  @return a <code>ListBuffer</code> with the same elements.   */  override def clone(): Buffer[A] = (new ListBuffer[A]) ++ this  /** Checks if two buffers are structurally identical.   *   *  @return <code>true</code>, iff both buffers contain the same sequence   *          of elements.   */  override def equals(obj: Any): Boolean = obj match {    case that: ListBuffer[_] =>      (this.length == that.length &&       elements.zip(that.elements).forall {         case (thiselem, thatelem) => thiselem == thatelem       })    case _ =>      false  }  /** Defines the prefix of the string representation.   *   *  @return the string representation of this buffer.   */  override protected def stringPrefix: String = "ListBuffer"}

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?