summaryrefslogtreecommitdiff
path: root/src/library/scala/collection
diff options
context:
space:
mode:
Diffstat (limited to 'src/library/scala/collection')
-rw-r--r--src/library/scala/collection/BitSetLike.scala35
-rw-r--r--src/library/scala/collection/BufferedIterator.scala6
-rw-r--r--src/library/scala/collection/GenMap.scala14
-rw-r--r--src/library/scala/collection/GenMapLike.scala36
-rw-r--r--src/library/scala/collection/GenSeqLike.scala1
-rw-r--r--src/library/scala/collection/GenTraversableLike.scala26
-rw-r--r--src/library/scala/collection/GenTraversableOnce.scala6
-rw-r--r--src/library/scala/collection/IndexedSeqLike.scala5
-rw-r--r--src/library/scala/collection/IndexedSeqOptimized.scala3
-rw-r--r--src/library/scala/collection/IterableLike.scala23
-rw-r--r--src/library/scala/collection/IterableProxy.scala2
-rw-r--r--src/library/scala/collection/IterableProxyLike.scala3
-rw-r--r--src/library/scala/collection/IterableViewLike.scala5
-rw-r--r--src/library/scala/collection/Iterator.scala281
-rw-r--r--src/library/scala/collection/JavaConversions.scala30
-rw-r--r--src/library/scala/collection/JavaConverters.scala82
-rw-r--r--src/library/scala/collection/LinearSeqOptimized.scala8
-rw-r--r--src/library/scala/collection/Map.scala24
-rw-r--r--src/library/scala/collection/MapLike.scala157
-rw-r--r--src/library/scala/collection/MapProxy.scala2
-rw-r--r--src/library/scala/collection/MapProxyLike.scala2
-rw-r--r--src/library/scala/collection/Parallelizable.scala2
-rw-r--r--src/library/scala/collection/SeqLike.scala8
-rw-r--r--src/library/scala/collection/SeqProxy.scala2
-rw-r--r--src/library/scala/collection/SeqProxyLike.scala2
-rw-r--r--src/library/scala/collection/SeqViewLike.scala22
-rw-r--r--src/library/scala/collection/SetLike.scala21
-rw-r--r--src/library/scala/collection/SetProxy.scala2
-rw-r--r--src/library/scala/collection/SetProxyLike.scala2
-rw-r--r--src/library/scala/collection/SortedSet.scala2
-rw-r--r--src/library/scala/collection/TraversableLike.scala74
-rw-r--r--src/library/scala/collection/TraversableOnce.scala2
-rw-r--r--src/library/scala/collection/TraversableProxy.scala2
-rw-r--r--src/library/scala/collection/TraversableProxyLike.scala2
-rw-r--r--src/library/scala/collection/TraversableViewLike.scala22
-rw-r--r--src/library/scala/collection/concurrent/Map.scala11
-rw-r--r--src/library/scala/collection/concurrent/TrieMap.scala50
-rw-r--r--src/library/scala/collection/convert/AsJavaConverters.scala262
-rw-r--r--src/library/scala/collection/convert/AsScalaConverters.scala207
-rw-r--r--src/library/scala/collection/convert/DecorateAsJava.scala250
-rw-r--r--src/library/scala/collection/convert/DecorateAsScala.scala155
-rw-r--r--src/library/scala/collection/convert/Decorators.scala10
-rw-r--r--src/library/scala/collection/convert/ImplicitConversions.scala171
-rw-r--r--src/library/scala/collection/convert/WrapAsJava.scala81
-rw-r--r--src/library/scala/collection/convert/WrapAsScala.scala70
-rw-r--r--src/library/scala/collection/convert/Wrappers.scala28
-rw-r--r--src/library/scala/collection/convert/package.scala9
-rw-r--r--src/library/scala/collection/generic/BitOperations.scala23
-rw-r--r--src/library/scala/collection/generic/GenSetFactory.scala6
-rw-r--r--src/library/scala/collection/generic/GenTraversableFactory.scala2
-rw-r--r--src/library/scala/collection/generic/GenericParTemplate.scala1
-rw-r--r--src/library/scala/collection/generic/IterableForwarder.scala2
-rw-r--r--src/library/scala/collection/generic/MapFactory.scala2
-rw-r--r--src/library/scala/collection/generic/MutableSortedMapFactory.scala24
-rw-r--r--src/library/scala/collection/generic/ParFactory.scala1
-rw-r--r--src/library/scala/collection/generic/ParSetFactory.scala1
-rw-r--r--src/library/scala/collection/generic/SeqForwarder.scala2
-rw-r--r--src/library/scala/collection/generic/SetFactory.scala1
-rw-r--r--src/library/scala/collection/generic/TraversableForwarder.scala2
-rw-r--r--src/library/scala/collection/generic/package.scala1
-rw-r--r--src/library/scala/collection/immutable/BitSet.scala41
-rw-r--r--src/library/scala/collection/immutable/HashMap.scala60
-rw-r--r--src/library/scala/collection/immutable/HashSet.scala40
-rw-r--r--src/library/scala/collection/immutable/List.scala23
-rw-r--r--src/library/scala/collection/immutable/ListMap.scala285
-rw-r--r--src/library/scala/collection/immutable/ListSet.scala222
-rw-r--r--src/library/scala/collection/immutable/Map.scala124
-rw-r--r--src/library/scala/collection/immutable/MapLike.scala55
-rw-r--r--src/library/scala/collection/immutable/MapProxy.scala2
-rw-r--r--src/library/scala/collection/immutable/NumericRange.scala22
-rw-r--r--src/library/scala/collection/immutable/PagedSeq.scala7
-rw-r--r--src/library/scala/collection/immutable/Queue.scala21
-rw-r--r--src/library/scala/collection/immutable/Range.scala73
-rw-r--r--src/library/scala/collection/immutable/Set.scala12
-rw-r--r--src/library/scala/collection/immutable/SetProxy.scala5
-rw-r--r--src/library/scala/collection/immutable/SortedMap.scala1
-rw-r--r--src/library/scala/collection/immutable/SortedSet.scala3
-rw-r--r--src/library/scala/collection/immutable/Stack.scala2
-rw-r--r--src/library/scala/collection/immutable/Stream.scala152
-rw-r--r--src/library/scala/collection/immutable/StreamViewLike.scala2
-rw-r--r--src/library/scala/collection/immutable/StringLike.scala147
-rw-r--r--src/library/scala/collection/immutable/Traversable.scala11
-rw-r--r--src/library/scala/collection/immutable/TreeMap.scala3
-rw-r--r--src/library/scala/collection/immutable/TreeSet.scala3
-rw-r--r--src/library/scala/collection/immutable/Vector.scala760
-rw-r--r--src/library/scala/collection/immutable/WrappedString.scala3
-rw-r--r--src/library/scala/collection/mutable/AVLTree.scala250
-rw-r--r--src/library/scala/collection/mutable/AnyRefMap.scala32
-rw-r--r--src/library/scala/collection/mutable/ArrayBuffer.scala15
-rw-r--r--src/library/scala/collection/mutable/ArrayBuilder.scala139
-rw-r--r--src/library/scala/collection/mutable/ArrayOps.scala75
-rw-r--r--src/library/scala/collection/mutable/ArraySeq.scala2
-rw-r--r--src/library/scala/collection/mutable/ArrayStack.scala7
-rw-r--r--src/library/scala/collection/mutable/BitSet.scala8
-rw-r--r--src/library/scala/collection/mutable/BufferLike.scala18
-rw-r--r--src/library/scala/collection/mutable/BufferProxy.scala6
-rw-r--r--src/library/scala/collection/mutable/Builder.scala39
-rw-r--r--src/library/scala/collection/mutable/DefaultMapModel.scala2
-rw-r--r--src/library/scala/collection/mutable/DoubleLinkedList.scala4
-rw-r--r--src/library/scala/collection/mutable/DoubleLinkedListLike.scala2
-rw-r--r--src/library/scala/collection/mutable/FlatHashTable.scala4
-rw-r--r--src/library/scala/collection/mutable/GrowingBuilder.scala4
-rw-r--r--src/library/scala/collection/mutable/HashMap.scala12
-rw-r--r--src/library/scala/collection/mutable/HashTable.scala21
-rw-r--r--src/library/scala/collection/mutable/History.scala2
-rw-r--r--src/library/scala/collection/mutable/ImmutableMapAdaptor.scala2
-rw-r--r--src/library/scala/collection/mutable/ImmutableSetAdaptor.scala2
-rw-r--r--src/library/scala/collection/mutable/IndexedSeqView.scala1
-rw-r--r--src/library/scala/collection/mutable/LazyBuilder.scala4
-rw-r--r--src/library/scala/collection/mutable/LinkedList.scala4
-rw-r--r--src/library/scala/collection/mutable/LinkedListLike.scala2
-rw-r--r--src/library/scala/collection/mutable/ListBuffer.scala48
-rw-r--r--src/library/scala/collection/mutable/LongMap.scala26
-rw-r--r--src/library/scala/collection/mutable/Map.scala40
-rw-r--r--src/library/scala/collection/mutable/MapBuilder.scala2
-rw-r--r--src/library/scala/collection/mutable/MapLike.scala70
-rw-r--r--src/library/scala/collection/mutable/MapProxy.scala2
-rw-r--r--src/library/scala/collection/mutable/MutableList.scala2
-rw-r--r--src/library/scala/collection/mutable/ObservableBuffer.scala5
-rw-r--r--src/library/scala/collection/mutable/ObservableMap.scala5
-rw-r--r--src/library/scala/collection/mutable/ObservableSet.scala5
-rw-r--r--src/library/scala/collection/mutable/OpenHashMap.scala86
-rw-r--r--src/library/scala/collection/mutable/PriorityQueue.scala304
-rw-r--r--src/library/scala/collection/mutable/PriorityQueueProxy.scala96
-rw-r--r--src/library/scala/collection/mutable/Queue.scala2
-rw-r--r--src/library/scala/collection/mutable/QueueProxy.scala2
-rw-r--r--src/library/scala/collection/mutable/RedBlackTree.scala580
-rw-r--r--src/library/scala/collection/mutable/ResizableArray.scala4
-rw-r--r--src/library/scala/collection/mutable/ReusableBuilder.scala49
-rw-r--r--src/library/scala/collection/mutable/SetBuilder.scala4
-rw-r--r--src/library/scala/collection/mutable/SetLike.scala13
-rw-r--r--src/library/scala/collection/mutable/SetProxy.scala2
-rw-r--r--src/library/scala/collection/mutable/SortedMap.scala57
-rw-r--r--src/library/scala/collection/mutable/SortedSet.scala7
-rw-r--r--src/library/scala/collection/mutable/Stack.scala1
-rw-r--r--src/library/scala/collection/mutable/StackProxy.scala2
-rw-r--r--src/library/scala/collection/mutable/StringBuilder.scala8
-rw-r--r--src/library/scala/collection/mutable/SynchronizedBuffer.scala4
-rw-r--r--src/library/scala/collection/mutable/SynchronizedMap.scala4
-rw-r--r--src/library/scala/collection/mutable/SynchronizedPriorityQueue.scala101
-rw-r--r--src/library/scala/collection/mutable/SynchronizedQueue.scala2
-rw-r--r--src/library/scala/collection/mutable/SynchronizedSet.scala4
-rw-r--r--src/library/scala/collection/mutable/SynchronizedStack.scala3
-rw-r--r--src/library/scala/collection/mutable/TreeMap.scala188
-rw-r--r--src/library/scala/collection/mutable/TreeSet.scala181
-rw-r--r--src/library/scala/collection/mutable/UnrolledBuffer.scala11
-rw-r--r--src/library/scala/collection/mutable/WrappedArray.scala63
-rw-r--r--src/library/scala/collection/mutable/WrappedArrayBuilder.scala11
-rw-r--r--src/library/scala/collection/package.scala8
-rw-r--r--src/library/scala/collection/parallel/ParIterableLike.scala22
-rw-r--r--src/library/scala/collection/parallel/ParMap.scala1
-rw-r--r--src/library/scala/collection/parallel/ParMapLike.scala4
-rw-r--r--src/library/scala/collection/parallel/ParSeqLike.scala15
-rw-r--r--src/library/scala/collection/parallel/RemainsIterator.scala12
-rw-r--r--src/library/scala/collection/parallel/TaskSupport.scala10
-rw-r--r--src/library/scala/collection/parallel/Tasks.scala23
-rw-r--r--src/library/scala/collection/parallel/immutable/ParHashSet.scala2
-rw-r--r--src/library/scala/collection/parallel/immutable/ParMap.scala1
-rw-r--r--src/library/scala/collection/parallel/immutable/ParRange.scala2
-rw-r--r--src/library/scala/collection/parallel/immutable/package.scala7
-rw-r--r--src/library/scala/collection/parallel/mutable/LazyCombiner.scala1
-rw-r--r--src/library/scala/collection/parallel/mutable/ParArray.scala1
-rw-r--r--src/library/scala/collection/parallel/mutable/ParTrieMap.scala15
-rw-r--r--src/library/scala/collection/parallel/mutable/ResizableParArrayCombiner.scala8
-rw-r--r--src/library/scala/collection/parallel/mutable/UnrolledParArrayCombiner.scala16
-rw-r--r--src/library/scala/collection/parallel/package.scala18
-rw-r--r--src/library/scala/collection/script/Location.scala10
-rw-r--r--src/library/scala/collection/script/Message.scala12
-rw-r--r--src/library/scala/collection/script/Scriptable.scala2
169 files changed, 4326 insertions, 2882 deletions
diff --git a/src/library/scala/collection/BitSetLike.scala b/src/library/scala/collection/BitSetLike.scala
index 29369447d1..f0a70170c2 100644
--- a/src/library/scala/collection/BitSetLike.scala
+++ b/src/library/scala/collection/BitSetLike.scala
@@ -77,26 +77,26 @@ trait BitSetLike[+This <: BitSetLike[This] with SortedSet[Int]] extends SortedSe
def rangeImpl(from: Option[Int], until: Option[Int]): This = {
val a = toBitMask
val len = a.length
- if(from.isDefined) {
+ if (from.isDefined) {
var f = from.get
var pos = 0
- while(f >= 64 && pos < len) {
+ while (f >= 64 && pos < len) {
f -= 64
a(pos) = 0
pos += 1
}
- if(f > 0 && pos < len) a(pos) &= ~((1L << f)-1)
+ if (f > 0 && pos < len) a(pos) &= ~((1L << f)-1)
}
- if(until.isDefined) {
+ if (until.isDefined) {
val u = until.get
val w = u / 64
val b = u % 64
var clearw = w+1
- while(clearw < len) {
+ while (clearw < len) {
a(clearw) = 0
clearw += 1
}
- if(w < len) a(w) &= (1L << b)-1
+ if (w < len) a(w) &= (1L << b)-1
}
fromBitMaskNoCopy(a)
}
@@ -204,12 +204,33 @@ trait BitSetLike[+This <: BitSetLike[This] with SortedSet[Int]] extends SortedSe
def subsetOf(other: BitSet): Boolean =
(0 until nwords) forall (idx => (this.word(idx) & ~ other.word(idx)) == 0L)
+ override def head: Int = {
+ val n = nwords
+ var i = 0
+ while (i < n) {
+ val wi = word(i)
+ if (wi != 0L) return WordLength*i + java.lang.Long.numberOfTrailingZeros(wi)
+ i += 1
+ }
+ throw new NoSuchElementException("Empty BitSet")
+ }
+
+ override def last: Int = {
+ var i = nwords - 1
+ while (i >= 0) {
+ val wi = word(i)
+ if (wi != 0L) return WordLength*i + 63 - java.lang.Long.numberOfLeadingZeros(wi)
+ i -= 1
+ }
+ throw new NoSuchElementException("Empty BitSet")
+ }
+
override def addString(sb: StringBuilder, start: String, sep: String, end: String) = {
sb append start
var pre = ""
val max = nwords * WordLength
var i = 0
- while(i != max) {
+ while (i != max) {
if (contains(i)) {
sb append pre append i
pre = sep
diff --git a/src/library/scala/collection/BufferedIterator.scala b/src/library/scala/collection/BufferedIterator.scala
index e6e97d584c..1424ef2fd0 100644
--- a/src/library/scala/collection/BufferedIterator.scala
+++ b/src/library/scala/collection/BufferedIterator.scala
@@ -24,5 +24,11 @@ trait BufferedIterator[+A] extends Iterator[A] {
*/
def head: A
+ /** Returns an option of the next element of an iterator without advancing beyond it.
+ * @return the next element of this iterator if it has a next element
+ * `None` if it does not
+ */
+ def headOption : Option[A] = if (hasNext) Some(head) else None
+
override def buffered: this.type = this
}
diff --git a/src/library/scala/collection/GenMap.scala b/src/library/scala/collection/GenMap.scala
index d17a2de179..6bc507ae93 100644
--- a/src/library/scala/collection/GenMap.scala
+++ b/src/library/scala/collection/GenMap.scala
@@ -18,18 +18,18 @@ import generic._
* @author Aleksandar Prokopec
* @since 2.9
*/
-trait GenMap[A, +B]
-extends GenMapLike[A, B, GenMap[A, B]]
- with GenIterable[(A, B)]
+trait GenMap[K, +V]
+extends GenMapLike[K, V, GenMap[K, V]]
+ with GenIterable[(K, V)]
{
- def seq: Map[A, B]
+ def seq: Map[K, V]
- def updated [B1 >: B](key: A, value: B1): GenMap[A, B1]
+ def updated [V1 >: V](key: K, value: V1): GenMap[K, V1]
}
object GenMap extends GenMapFactory[GenMap] {
- def empty[A, B]: immutable.Map[A, B] = immutable.Map.empty
+ def empty[K, V]: immutable.Map[K, V] = immutable.Map.empty
/** $mapCanBuildFromInfo */
- implicit def canBuildFrom[A, B]: CanBuildFrom[Coll, (A, B), GenMap[A, B]] = new MapCanBuildFrom[A, B]
+ implicit def canBuildFrom[K, V]: CanBuildFrom[Coll, (K, V), GenMap[K, V]] = new MapCanBuildFrom[K, V]
}
diff --git a/src/library/scala/collection/GenMapLike.scala b/src/library/scala/collection/GenMapLike.scala
index 2b39fa2289..f6c2d071b5 100644
--- a/src/library/scala/collection/GenMapLike.scala
+++ b/src/library/scala/collection/GenMapLike.scala
@@ -22,13 +22,13 @@ package collection
* A map is a collection of bindings from keys to values, where there are
* no duplicate keys.
*/
-trait GenMapLike[A, +B, +Repr] extends GenIterableLike[(A, B), Repr] with Equals with Parallelizable[(A, B), parallel.ParMap[A, B]] {
- def default(key: A): B
- def get(key: A): Option[B]
- def apply(key: A): B
- def seq: Map[A, B]
- def +[B1 >: B](kv: (A, B1)): GenMap[A, B1]
- def - (key: A): Repr
+trait GenMapLike[K, +V, +Repr] extends GenIterableLike[(K, V), Repr] with Equals with Parallelizable[(K, V), parallel.ParMap[K, V]] {
+ def default(key: K): V
+ def get(key: K): Option[V]
+ def apply(key: K): V
+ def seq: Map[K, V]
+ def +[V1 >: V](kv: (K, V1)): GenMap[K, V1]
+ def - (key: K): Repr
// This hash code must be symmetric in the contents but ought not
// collide trivially.
@@ -41,17 +41,17 @@ trait GenMapLike[A, +B, +Repr] extends GenIterableLike[(A, B), Repr] with Equals
* @tparam B1 the result type of the default computation.
* @return the value associated with `key` if it exists,
* otherwise the result of the `default` computation.
- * @usecase def getOrElse(key: A, default: => B): B
+ * @usecase def getOrElse(key: K, default: => V): V
* @inheritdoc
*/
- def getOrElse[B1 >: B](key: A, default: => B1): B1
+ def getOrElse[V1 >: V](key: K, default: => V1): V1
/** Tests whether this map contains a binding for a key.
*
* @param key the key
* @return `true` if there is a binding for `key` in this map, `false` otherwise.
*/
- def contains(key: A): Boolean
+ def contains(key: K): Boolean
/** Tests whether this map contains a binding for a key. This method,
* which implements an abstract method of trait `PartialFunction`,
@@ -60,47 +60,47 @@ trait GenMapLike[A, +B, +Repr] extends GenIterableLike[(A, B), Repr] with Equals
* @param key the key
* @return `true` if there is a binding for `key` in this map, `false` otherwise.
*/
- def isDefinedAt(key: A): Boolean
+ def isDefinedAt(key: K): Boolean
- def keySet: GenSet[A]
+ def keySet: GenSet[K]
/** Collects all keys of this map in an iterable collection.
*
* @return the keys of this map as an iterable.
*/
- def keys: GenIterable[A]
+ def keys: GenIterable[K]
/** Collects all values of this map in an iterable collection.
*
* @return the values of this map as an iterable.
*/
- def values: GenIterable[B]
+ def values: GenIterable[V]
/** Creates an iterator for all keys.
*
* @return an iterator over all keys.
*/
- def keysIterator: Iterator[A]
+ def keysIterator: Iterator[K]
/** Creates an iterator for all values in this map.
*
* @return an iterator over all values that are associated with some key in this map.
*/
- def valuesIterator: Iterator[B]
+ def valuesIterator: Iterator[V]
/** Filters this map by retaining only keys satisfying a predicate.
* @param p the predicate used to test keys
* @return an immutable map consisting only of those key value pairs of this map where the key satisfies
* the predicate `p`. The resulting map wraps the original map without copying any elements.
*/
- def filterKeys(p: A => Boolean): GenMap[A, B]
+ def filterKeys(p: K => Boolean): GenMap[K, V]
/** Transforms this map by applying a function to every retrieved value.
* @param f the function used to transform values of this map.
* @return a map view which maps every key of this map
* to `f(this(key))`. The resulting map wraps the original map without copying any elements.
*/
- def mapValues[C](f: B => C): GenMap[A, C]
+ def mapValues[W](f: V => W): GenMap[K, W]
/** Compares two maps structurally; i.e., checks if all mappings
* contained in this map are also contained in the other map,
diff --git a/src/library/scala/collection/GenSeqLike.scala b/src/library/scala/collection/GenSeqLike.scala
index be1da1660a..405d8d7e57 100644
--- a/src/library/scala/collection/GenSeqLike.scala
+++ b/src/library/scala/collection/GenSeqLike.scala
@@ -58,6 +58,7 @@ trait GenSeqLike[+A, +Repr] extends Any with GenIterableLike[A, Repr] with Equal
* Note: `xs.length` and `xs.size` yield the same result.
*
* @return the number of elements in this $coll.
+ * @throws IllegalArgumentException if the length of the sequence cannot be represented in an `Int`, for example, `(-1 to Int.MaxValue).length`.
*/
def length: Int
diff --git a/src/library/scala/collection/GenTraversableLike.scala b/src/library/scala/collection/GenTraversableLike.scala
index d730996be2..0ee5542e30 100644
--- a/src/library/scala/collection/GenTraversableLike.scala
+++ b/src/library/scala/collection/GenTraversableLike.scala
@@ -24,7 +24,7 @@ import scala.annotation.migration
* is found.
* @define bfinfo an implicit value of class `CanBuildFrom` which determines
* the result class `That` from the current representation type `Repr` and
- * and the new element type `B`.
+ * the new element type `B`.
* @define orderDependent
*
* Note: might return different results for different runs, unless the
@@ -249,30 +249,6 @@ trait GenTraversableLike[+A, +Repr] extends Any with GenTraversableOnce[A] with
* @param bf $bfinfo
* @return a new collection of type `That` which contains all elements
* of this $coll followed by all elements of `that`.
- *
- * @usecase def ++[B](that: GenTraversableOnce[B]): $Coll[B]
- * @inheritdoc
- *
- * Example:
- * {{{
- * scala> val a = List(1)
- * a: List[Int] = List(1)
- *
- * scala> val b = List(2)
- * b: List[Int] = List(2)
- *
- * scala> val c = a ++ b
- * c: List[Int] = List(1, 2)
- *
- * scala> val d = List('a')
- * d: List[Char] = List(a)
- *
- * scala> val e = c ++ d
- * e: List[AnyVal] = List(1, 2, a)
- * }}}
- *
- * @return a new $coll which contains all elements of this $coll
- * followed by all elements of `that`.
*/
def ++[B >: A, That](that: GenTraversableOnce[B])(implicit bf: CanBuildFrom[Repr, B, That]): That
diff --git a/src/library/scala/collection/GenTraversableOnce.scala b/src/library/scala/collection/GenTraversableOnce.scala
index 4af2ca23be..f87f7654bc 100644
--- a/src/library/scala/collection/GenTraversableOnce.scala
+++ b/src/library/scala/collection/GenTraversableOnce.scala
@@ -96,6 +96,12 @@ trait GenTraversableOnce[+A] extends Any {
*/
def size: Int
+ /** The size of this $coll, if it can be cheaply computed
+ *
+ * @return the number of elements in this $coll, or -1 if the size cannot be determined cheaply
+ */
+ protected[collection] def sizeHintIfCheap: Int = -1
+
/** Tests whether the $coll is empty.
*
* Note: Implementations in subclasses that are not repeatedly traversable must take
diff --git a/src/library/scala/collection/IndexedSeqLike.scala b/src/library/scala/collection/IndexedSeqLike.scala
index 18c9175ee1..f0cede224d 100644
--- a/src/library/scala/collection/IndexedSeqLike.scala
+++ b/src/library/scala/collection/IndexedSeqLike.scala
@@ -9,9 +9,6 @@
package scala
package collection
-import mutable.ArrayBuffer
-import scala.annotation.tailrec
-
/** A template trait for indexed sequences of type `IndexedSeq[A]`.
*
* $indexedSeqInfo
@@ -95,4 +92,6 @@ trait IndexedSeqLike[+A, +Repr] extends Any with SeqLike[A, Repr] {
copyToBuffer(result)
result
}
+
+ override protected[collection] def sizeHintIfCheap: Int = size
}
diff --git a/src/library/scala/collection/IndexedSeqOptimized.scala b/src/library/scala/collection/IndexedSeqOptimized.scala
index a7e06b4d1a..320725c30e 100644
--- a/src/library/scala/collection/IndexedSeqOptimized.scala
+++ b/src/library/scala/collection/IndexedSeqOptimized.scala
@@ -10,7 +10,6 @@ package scala
package collection
import generic._
-import mutable.ArrayBuffer
import scala.annotation.tailrec
/** A template trait for indexed sequences of type `IndexedSeq[A]` which optimizes
@@ -200,7 +199,7 @@ trait IndexedSeqOptimized[+A, +Repr] extends Any with IndexedSeqLike[A, Repr] {
override /*SeqLike*/
def indexWhere(p: A => Boolean, from: Int): Int = {
- val start = from max 0
+ val start = math.max(from, 0)
negLength(start + segmentLength(!p(_), start))
}
diff --git a/src/library/scala/collection/IterableLike.scala b/src/library/scala/collection/IterableLike.scala
index ecf64624e8..419206c226 100644
--- a/src/library/scala/collection/IterableLike.scala
+++ b/src/library/scala/collection/IterableLike.scala
@@ -10,8 +10,7 @@ package scala
package collection
import generic._
-import immutable.{ List, Stream }
-import scala.annotation.unchecked.uncheckedVariance
+import immutable.Stream
/** A template trait for iterable collections of type `Iterable[A]`.
* $iterableInfo
@@ -83,8 +82,8 @@ self =>
iterator.foldRight(z)(op)
override /*TraversableLike*/ def reduceRight[B >: A](op: (A, B) => B): B =
iterator.reduceRight(op)
-
-
+
+
/** Returns this $coll as an iterable collection.
*
* A new collection will not be built; lazy collections will stay lazy.
@@ -94,7 +93,7 @@ self =>
*/
override /*TraversableLike*/ def toIterable: Iterable[A] =
thisCollection
-
+
/** Returns an Iterator over the elements in this $coll. Produces the same
* result as `iterator`.
* $willNotTerminateInf
@@ -102,7 +101,7 @@ self =>
*/
@deprecatedOverriding("toIterator should stay consistent with iterator for all Iterables: override iterator instead.", "2.11.0")
override def toIterator: Iterator[A] = iterator
-
+
override /*TraversableLike*/ def head: A =
iterator.next()
@@ -178,14 +177,14 @@ self =>
}
/** Groups elements in fixed size blocks by passing a "sliding window"
- * over them (as opposed to partitioning them, as is done in grouped.)
- * "Sliding window" step is 1 by default.
+ * over them (as opposed to partitioning them, as is done in `grouped`.)
+ * The "sliding window" step is set to one.
* @see [[scala.collection.Iterator]], method `sliding`
*
* @param size the number of elements per group
* @return An iterator producing ${coll}s of size `size`, except the
- * last and the only element will be truncated if there are
- * fewer elements than size.
+ * last element (which may be the only element) will be truncated
+ * if there are fewer than `size` elements remaining to be grouped.
*/
def sliding(size: Int): Iterator[Repr] = sliding(size, 1)
@@ -197,8 +196,8 @@ self =>
* @param step the distance between the first elements of successive
* groups
* @return An iterator producing ${coll}s of size `size`, except the
- * last and the only element will be truncated if there are
- * fewer elements than size.
+ * last element (which may be the only element) will be truncated
+ * if there are fewer than `size` elements remaining to be grouped.
*/
def sliding(size: Int, step: Int): Iterator[Repr] =
for (xs <- iterator.sliding(size, step)) yield {
diff --git a/src/library/scala/collection/IterableProxy.scala b/src/library/scala/collection/IterableProxy.scala
index 97aa830c5a..5f4d69c411 100644
--- a/src/library/scala/collection/IterableProxy.scala
+++ b/src/library/scala/collection/IterableProxy.scala
@@ -16,5 +16,5 @@ package collection
* @version 2.8
* @since 2.8
*/
-@deprecated("Proxying is deprecated due to lack of use and compiler-level support.", "2.11.3")
+@deprecated("proxying is deprecated due to lack of use and compiler-level support", "2.11.3")
trait IterableProxy[+A] extends Iterable[A] with IterableProxyLike[A, Iterable[A]]
diff --git a/src/library/scala/collection/IterableProxyLike.scala b/src/library/scala/collection/IterableProxyLike.scala
index 90e630ee28..f87089cba8 100644
--- a/src/library/scala/collection/IterableProxyLike.scala
+++ b/src/library/scala/collection/IterableProxyLike.scala
@@ -12,7 +12,6 @@ package scala
package collection
import generic._
-import mutable.Buffer
// Methods could be printed by cat IterableLike.scala | egrep '^ (override )?def'
@@ -23,7 +22,7 @@ import mutable.Buffer
* @version 2.8
* @since 2.8
*/
-@deprecated("Proxying is deprecated due to lack of use and compiler-level support.", "2.11.0")
+@deprecated("proxying is deprecated due to lack of use and compiler-level support", "2.11.0")
trait IterableProxyLike[+A, +Repr <: IterableLike[A, Repr] with Iterable[A]]
extends IterableLike[A, Repr]
with TraversableProxyLike[A, Repr] {
diff --git a/src/library/scala/collection/IterableViewLike.scala b/src/library/scala/collection/IterableViewLike.scala
index b84d90c51b..c254ed7480 100644
--- a/src/library/scala/collection/IterableViewLike.scala
+++ b/src/library/scala/collection/IterableViewLike.scala
@@ -69,6 +69,10 @@ trait IterableViewLike[+A,
trait Appended[B >: A] extends super.Appended[B] with Transformed[B] {
def iterator = self.iterator ++ rest
}
+
+ trait Prepended[B >: A] extends super.Prepended[B] with Transformed[B] {
+ def iterator = fst.toIterator ++ self
+ }
trait Filtered extends super.Filtered with Transformed[A] {
def iterator = self.iterator filter pred
@@ -110,6 +114,7 @@ trait IterableViewLike[+A,
} with AbstractTransformed[(A1, B)] with ZippedAll[A1, B]
protected override def newForced[B](xs: => GenSeq[B]): Transformed[B] = new { val forced = xs } with AbstractTransformed[B] with Forced[B]
protected override def newAppended[B >: A](that: GenTraversable[B]): Transformed[B] = new { val rest = that } with AbstractTransformed[B] with Appended[B]
+ protected override def newPrepended[B >: A](that: GenTraversable[B]): Transformed[B] = new { val fst = that } with AbstractTransformed[B] with Prepended[B]
protected override def newMapped[B](f: A => B): Transformed[B] = new { val mapping = f } with AbstractTransformed[B] with Mapped[B]
protected override def newFlatMapped[B](f: A => GenTraversableOnce[B]): Transformed[B] = new { val mapping = f } with AbstractTransformed[B] with FlatMapped[B]
protected override def newFiltered(p: A => Boolean): Transformed[A] = new { val pred = p } with AbstractTransformed[A] with Filtered
diff --git a/src/library/scala/collection/Iterator.scala b/src/library/scala/collection/Iterator.scala
index 03b9fbff26..809e851494 100644
--- a/src/library/scala/collection/Iterator.scala
+++ b/src/library/scala/collection/Iterator.scala
@@ -11,9 +11,8 @@ package collection
import mutable.ArrayBuffer
import scala.annotation.{tailrec, migration}
+import scala.annotation.unchecked.{uncheckedVariance => uV}
import immutable.Stream
-import scala.collection.generic.CanBuildFrom
-import scala.annotation.unchecked.{ uncheckedVariance => uV }
/** The `Iterator` object provides various functions for creating specialized iterators.
*
@@ -162,30 +161,49 @@ object Iterator {
def next = elem
}
- /** Avoid stack overflows when applying ++ to lots of iterators by
- * flattening the unevaluated iterators out into a vector of closures.
+ /** Creates an iterator to which other iterators can be appended efficiently.
+ * Nested ConcatIterators are merged to avoid blowing the stack.
*/
- private[scala] final class ConcatIterator[+A](private[this] var current: Iterator[A], initial: Vector[() => Iterator[A]]) extends Iterator[A] {
- @deprecated def this(initial: Vector[() => Iterator[A]]) = this(Iterator.empty, initial) // for binary compatibility
- private[this] var queue: Vector[() => Iterator[A]] = initial
- private[this] var currentHasNextChecked = false
+ private final class ConcatIterator[+A](private var current: Iterator[A @uV]) extends Iterator[A] {
+ private var tail: ConcatIteratorCell[A @uV] = null
+ private var last: ConcatIteratorCell[A @uV] = null
+ private var currentHasNextChecked = false
+
// Advance current to the next non-empty iterator
// current is set to null when all iterators are exhausted
@tailrec
private[this] def advance(): Boolean = {
- if (queue.isEmpty) {
+ if (tail eq null) {
current = null
+ last = null
false
}
else {
- current = queue.head()
- queue = queue.tail
- if (current.hasNext) {
+ current = tail.headIterator
+ tail = tail.tail
+ merge()
+ if (currentHasNextChecked) true
+ else if (current.hasNext) {
currentHasNextChecked = true
true
} else advance()
}
}
+
+ // If the current iterator is a ConcatIterator, merge it into this one
+ @tailrec
+ private[this] def merge(): Unit =
+ if (current.isInstanceOf[ConcatIterator[_]]) {
+ val c = current.asInstanceOf[ConcatIterator[A]]
+ current = c.current
+ currentHasNextChecked = c.currentHasNextChecked
+ if (c.tail ne null) {
+ c.last.tail = tail
+ tail = c.tail
+ }
+ merge()
+ }
+
def hasNext =
if (currentHasNextChecked) true
else if (current eq null) false
@@ -193,48 +211,73 @@ object Iterator {
currentHasNextChecked = true
true
} else advance()
+
def next() =
if (hasNext) {
currentHasNextChecked = false
current.next()
} else Iterator.empty.next()
- override def ++[B >: A](that: => GenTraversableOnce[B]): Iterator[B] =
- if(current eq null) new JoinIterator(Iterator.empty, that)
- else new ConcatIterator(current, queue :+ (() => that.toIterator))
+ override def ++[B >: A](that: => GenTraversableOnce[B]): Iterator[B] = {
+ val c = new ConcatIteratorCell[B](that, null).asInstanceOf[ConcatIteratorCell[A]]
+ if(tail eq null) {
+ tail = c
+ last = c
+ } else {
+ last.tail = c
+ last = c
+ }
+ if(current eq null) current = Iterator.empty
+ this
+ }
}
- private[scala] final class JoinIterator[+A](lhs: Iterator[A], that: => GenTraversableOnce[A]) extends Iterator[A] {
- private[this] var state = 0 // 0: lhs not checked, 1: lhs has next, 2: switched to rhs
- private[this] lazy val rhs: Iterator[A] = that.toIterator
- def hasNext = state match {
- case 0 =>
- if (lhs.hasNext) {
- state = 1
- true
- } else {
- state = 2
- rhs.hasNext
- }
- case 1 => true
- case _ => rhs.hasNext
+ private[this] final class ConcatIteratorCell[A](head: => GenTraversableOnce[A], var tail: ConcatIteratorCell[A]) {
+ def headIterator: Iterator[A] = head.toIterator
+ }
+
+ /** Creates a delegating iterator capped by a limit count. Negative limit means unbounded.
+ * Lazily skip to start on first evaluation. Avoids daisy-chained iterators due to slicing.
+ */
+ private[scala] final class SliceIterator[A](val underlying: Iterator[A], start: Int, limit: Int) extends AbstractIterator[A] {
+ private var remaining = limit
+ private var dropping = start
+ @inline private def unbounded = remaining < 0
+ private def skip(): Unit =
+ while (dropping > 0) {
+ if (underlying.hasNext) {
+ underlying.next()
+ dropping -= 1
+ } else
+ dropping = 0
+ }
+ def hasNext = { skip(); remaining != 0 && underlying.hasNext }
+ def next() = {
+ skip()
+ if (remaining > 0) {
+ remaining -= 1
+ underlying.next()
+ }
+ else if (unbounded) underlying.next()
+ else empty.next()
}
- def next() = state match {
- case 0 =>
- if (lhs.hasNext) lhs.next()
- else {
- state = 2
- rhs.next()
- }
- case 1 =>
- state = 0
- lhs.next()
- case _ =>
- rhs.next()
+ override protected def sliceIterator(from: Int, until: Int): Iterator[A] = {
+ val lo = from max 0
+ def adjustedBound =
+ if (unbounded) -1
+ else 0 max (remaining - lo)
+ val rest =
+ if (until < 0) adjustedBound // respect current bound, if any
+ else if (until <= lo) 0 // empty
+ else if (unbounded) until - lo // now finite
+ else adjustedBound min (until - lo) // keep lesser bound
+ if (rest == 0) empty
+ else {
+ dropping += lo
+ remaining = rest
+ this
+ }
}
-
- override def ++[B >: A](that: => GenTraversableOnce[B]) =
- new ConcatIterator(this, Vector(() => that.toIterator))
}
}
@@ -347,11 +390,11 @@ trait Iterator[+A] extends TraversableOnce[A] {
/** Selects first ''n'' values of this iterator.
*
* @param n the number of values to take
- * @return an iterator producing only of the first `n` values of this iterator, or else the
+ * @return an iterator producing only the first `n` values of this iterator, or else the
* whole iterator, if it produces fewer than `n` values.
* @note Reuse: $consumesAndProducesIterator
*/
- def take(n: Int): Iterator[A] = slice(0, n)
+ def take(n: Int): Iterator[A] = sliceIterator(0, n max 0)
/** Advances this iterator past the first ''n'' elements, or the length of the iterator, whichever is smaller.
*
@@ -372,29 +415,24 @@ trait Iterator[+A] extends TraversableOnce[A] {
/** Creates an iterator returning an interval of the values produced by this iterator.
*
* @param from the index of the first element in this iterator which forms part of the slice.
- * @param until the index of the first element following the slice.
+ * If negative, the slice starts at zero.
+ * @param until the index of the first element following the slice. If negative, the slice is empty.
* @return an iterator which advances this iterator past the first `from` elements using `drop`,
* and then takes `until - from` elements, using `take`.
* @note Reuse: $consumesAndProducesIterator
*/
- def slice(from: Int, until: Int): Iterator[A] = {
+ def slice(from: Int, until: Int): Iterator[A] = sliceIterator(from, until max 0)
+
+ /** Creates an optionally bounded slice, unbounded if `until` is negative. */
+ protected def sliceIterator(from: Int, until: Int): Iterator[A] = {
val lo = from max 0
- var toDrop = lo
- while (toDrop > 0 && self.hasNext) {
- self.next()
- toDrop -= 1
- }
+ val rest =
+ if (until < 0) -1 // unbounded
+ else if (until <= lo) 0 // empty
+ else until - lo // finite
- new AbstractIterator[A] {
- private var remaining = until - lo
- def hasNext = remaining > 0 && self.hasNext
- def next(): A =
- if (remaining > 0) {
- remaining -= 1
- self.next()
- }
- else empty.next()
- }
+ if (rest == 0) empty
+ else new Iterator.SliceIterator(this, lo, rest)
}
/** Creates a new iterator that maps all produced values of this iterator
@@ -420,7 +458,7 @@ trait Iterator[+A] extends TraversableOnce[A] {
* @usecase def ++(that: => Iterator[A]): Iterator[A]
* @inheritdoc
*/
- def ++[B >: A](that: => GenTraversableOnce[B]): Iterator[B] = new Iterator.JoinIterator(self, that)
+ def ++[B >: A](that: => GenTraversableOnce[B]): Iterator[B] = new Iterator.ConcatIterator(self) ++ that
/** Creates a new iterator by applying a function to all values produced by this iterator
* and concatenating the results.
@@ -522,13 +560,13 @@ trait Iterator[+A] extends TraversableOnce[A] {
def collect[B](pf: PartialFunction[A, B]): Iterator[B] = new AbstractIterator[B] {
// Manually buffer to avoid extra layer of wrapping with buffered
private[this] var hd: A = _
-
+
// Little state machine to keep track of where we are
// Seek = 0; Found = 1; Empty = -1
// Not in vals because scalac won't make them static (@inline def only works with -optimize)
// BE REALLY CAREFUL TO KEEP COMMENTS AND NUMBERS IN SYNC!
private[this] var status = 0/*Seek*/
-
+
def hasNext = {
while (status == 0/*Seek*/) {
if (self.hasNext) {
@@ -698,13 +736,13 @@ trait Iterator[+A] extends TraversableOnce[A] {
}
def trailer: A = hd
}
-
+
val leading = new Leading
-
+
val trailing = new AbstractIterator[A] {
private[this] var myLeading = leading
- /* Status flags meanings:
- * -1 not yet accesssed
+ /* Status flag meanings:
+ * -1 not yet accessed
* 0 single element waiting in leading
* 1 defer to self
*/
@@ -736,7 +774,7 @@ trait Iterator[+A] extends TraversableOnce[A] {
}
else Iterator.empty.next()
}
-
+
override def toString = "unknown-if-empty iterator"
}
@@ -770,7 +808,7 @@ trait Iterator[+A] extends TraversableOnce[A] {
status = 1
false
}
- def next() =
+ def next() =
if (hasNext) {
if (status == 1) self.next()
else {
@@ -953,8 +991,25 @@ trait Iterator[+A] extends TraversableOnce[A] {
* or -1 if such an element does not exist until the end of the iterator is reached.
* @note Reuse: $consumesIterator
*/
- def indexWhere(p: A => Boolean): Int = {
+ def indexWhere(p: A => Boolean): Int = indexWhere(p, 0)
+
+ /** Returns the index of the first produced value satisfying a predicate, or -1, after or at
+ * some start index.
+ * $mayNotTerminateInf
+ *
+ * @param p the predicate to test values
+ * @param from the start index
+ * @return the index `>= from` of the first produced value satisfying `p`,
+ * or -1 if such an element does not exist until the end of the iterator is reached.
+ * @note Reuse: $consumesIterator
+ */
+ def indexWhere(p: A => Boolean, from: Int): Int = {
var i = 0
+ while (i < from && hasNext) {
+ next()
+ i += 1
+ }
+
while (hasNext) {
if (p(next())) return i
i += 1
@@ -971,8 +1026,26 @@ trait Iterator[+A] extends TraversableOnce[A] {
* or -1 if such an element does not exist until the end of the iterator is reached.
* @note Reuse: $consumesIterator
*/
- def indexOf[B >: A](elem: B): Int = {
+ def indexOf[B >: A](elem: B): Int = indexOf(elem, 0)
+
+ /** Returns the index of the first occurrence of the specified object in this iterable object
+ * after or at some start index.
+ * $mayNotTerminateInf
+ *
+ * @param elem element to search for.
+ * @param from the start index
+ * @return the index `>= from` of the first occurrence of `elem` in the values produced by this
+ * iterator, or -1 if such an element does not exist until the end of the iterator is
+ * reached.
+ * @note Reuse: $consumesIterator
+ */
+ def indexOf[B >: A](elem: B, from: Int): Int = {
var i = 0
+ while (i < from && hasNext) {
+ next()
+ i += 1
+ }
+
while (hasNext) {
if (next() == elem) return i
i += 1
@@ -1018,7 +1091,7 @@ trait Iterator[+A] extends TraversableOnce[A] {
extends AbstractIterator[Seq[B]]
with Iterator[Seq[B]] {
- require(size >= 1 && step >= 1, "size=%d and step=%d, but both must be positive".format(size, step))
+ require(size >= 1 && step >= 1, f"size=$size%d and step=$step%d, but both must be positive")
private[this] var buffer: ArrayBuffer[B] = ArrayBuffer() // the buffer
private[this] var filled = false // whether the buffer is "hot"
@@ -1026,30 +1099,30 @@ trait Iterator[+A] extends TraversableOnce[A] {
private[this] var pad: Option[() => B] = None // what to pad short sequences with
/** Public functions which can be used to configure the iterator before use.
- *
- * Pads the last segment if necessary so that all segments will
- * have the same size.
- *
- * @param x The element that will be appended to the last segment, if necessary.
- * @return The same iterator, and ''not'' a new iterator.
- * @note This method mutates the iterator it is called on, which can be safely used afterwards.
- * @note This method is mutually exclusive with `withPartial(true)`.
- */
+ *
+ * Pads the last segment if necessary so that all segments will
+ * have the same size.
+ *
+ * @param x The element that will be appended to the last segment, if necessary.
+ * @return The same iterator, and ''not'' a new iterator.
+ * @note This method mutates the iterator it is called on, which can be safely used afterwards.
+ * @note This method is mutually exclusive with `withPartial(true)`.
+ */
def withPadding(x: => B): this.type = {
pad = Some(() => x)
this
}
- /** Public functions which can be used to configure the iterator before use.
- *
- * Select whether the last segment may be returned with less than `size`
- * elements. If not, some elements of the original iterator may not be
- * returned at all.
- *
- * @param x `true` if partial segments may be returned, `false` otherwise.
- * @return The same iterator, and ''not'' a new iterator.
- * @note This method mutates the iterator it is called on, which can be safely used afterwards.
- * @note This method is mutually exclusive with `withPadding`.
- */
+ /** Public functions which can be used to configure the iterator before use.
+ *
+ * Select whether the last segment may be returned with less than `size`
+ * elements. If not, some elements of the original iterator may not be
+ * returned at all.
+ *
+ * @param x `true` if partial segments may be returned, `false` otherwise.
+ * @return The same iterator, and ''not'' a new iterator.
+ * @note This method mutates the iterator it is called on, which can be safely used afterwards.
+ * @note This method is mutually exclusive with `withPadding`.
+ */
def withPartial(x: Boolean): this.type = {
_partial = x
if (_partial == true) // reset pad since otherwise it will take precedence
@@ -1158,9 +1231,15 @@ trait Iterator[+A] extends TraversableOnce[A] {
new GroupedIterator[B](self, size, size)
/** Returns an iterator which presents a "sliding window" view of
- * another iterator. The first argument is the window size, and
- * the second is how far to advance the window on each iteration;
- * defaults to `1`. Example usages:
+ * this iterator. The first argument is the window size, and
+ * the second argument `step` is how far to advance the window
+ * on each iteration. The `step` defaults to `1`.
+ *
+ * The default `GroupedIterator` can be configured to either
+ * pad a partial result to size `size` or suppress the partial
+ * result entirely.
+ *
+ * Example usages:
* {{{
* // Returns List(List(1, 2, 3), List(2, 3, 4), List(3, 4, 5))
* (1 to 5).iterator.sliding(3).toList
@@ -1174,6 +1253,11 @@ trait Iterator[+A] extends TraversableOnce[A] {
* (1 to 5).iterator.sliding(4, 3).withPadding(it2.next).toList
* }}}
*
+ * @return An iterator producing `Seq[B]`s of size `size`, except the
+ * last element (which may be the only element) will be truncated
+ * if there are fewer than `size` elements remaining to be grouped.
+ * This behavior can be configured.
+ *
* @note Reuse: $consumesAndProducesIterator
*/
def sliding[B >: A](size: Int, step: Int = 1): GroupedIterator[B] =
@@ -1287,7 +1371,6 @@ trait Iterator[+A] extends TraversableOnce[A] {
* $willNotTerminateInf
*/
def copyToArray[B >: A](xs: Array[B], start: Int, len: Int): Unit = {
- require(start >= 0 && (start < xs.length || xs.length == 0), s"start $start out of range ${xs.length}")
var i = start
val end = start + math.min(len, xs.length - start)
while (i < end && hasNext) {
diff --git a/src/library/scala/collection/JavaConversions.scala b/src/library/scala/collection/JavaConversions.scala
index 7bfa60771f..93994d80bf 100644
--- a/src/library/scala/collection/JavaConversions.scala
+++ b/src/library/scala/collection/JavaConversions.scala
@@ -1,6 +1,6 @@
/* __ *\
** ________ ___ / / ___ Scala API **
-** / __/ __// _ | / / / _ | (c) 2006-2013, LAMP/EPFL **
+** / __/ __// _ | / / / _ | (c) 2006-2016, LAMP/EPFL **
** __\ \/ /__/ __ |/ /__/ __ | http://www.scala-lang.org/ **
** /____/\___/_/ |_/____/_/ | | **
** |/ **
@@ -11,21 +11,21 @@ package collection
import convert._
-/** A collection of implicit conversions supporting interoperability between
- * Scala and Java collections.
+/** A variety of implicit conversions supporting interoperability between
+ * Scala and Java collections.
*
- * The following conversions are supported:
+ * The following conversions are supported:
*{{{
- * scala.collection.Iterable <=> java.lang.Iterable
- * scala.collection.Iterable <=> java.util.Collection
- * scala.collection.Iterator <=> java.util.{ Iterator, Enumeration }
+ * scala.collection.Iterable <=> java.lang.Iterable
+ * scala.collection.Iterable <=> java.util.Collection
+ * scala.collection.Iterator <=> java.util.{ Iterator, Enumeration }
* scala.collection.mutable.Buffer <=> java.util.List
- * scala.collection.mutable.Set <=> java.util.Set
- * scala.collection.mutable.Map <=> java.util.{ Map, Dictionary }
+ * scala.collection.mutable.Set <=> java.util.Set
+ * scala.collection.mutable.Map <=> java.util.{ Map, Dictionary }
* scala.collection.concurrent.Map <=> java.util.concurrent.ConcurrentMap
*}}}
- * In all cases, converting from a source type to a target type and back
- * again will return the original source object, eg.
+ * In all cases, converting from a source type to a target type and back
+ * again will return the original source object:
*
*{{{
* import scala.collection.JavaConversions._
@@ -45,8 +45,16 @@ import convert._
* java.util.Properties => scala.collection.mutable.Map[String, String]
*}}}
*
+ * The transparent conversions provided here are considered
+ * fragile because they can result in unexpected behavior and performance.
+ *
+ * Therefore, this API has been deprecated and `JavaConverters` should be
+ * used instead. `JavaConverters` provides the same conversions, but through
+ * extension methods.
+ *
* @author Miles Sabin
* @author Martin Odersky
* @since 2.8
*/
+@deprecated("use JavaConverters", since="2.12.0")
object JavaConversions extends WrapAsScala with WrapAsJava
diff --git a/src/library/scala/collection/JavaConverters.scala b/src/library/scala/collection/JavaConverters.scala
index 86e86d4584..2337f0ef84 100644
--- a/src/library/scala/collection/JavaConverters.scala
+++ b/src/library/scala/collection/JavaConverters.scala
@@ -1,6 +1,6 @@
/* __ *\
** ________ ___ / / ___ Scala API **
-** / __/ __// _ | / / / _ | (c) 2006-2013, LAMP/EPFL **
+** / __/ __// _ | / / / _ | (c) 2006-2016, LAMP/EPFL **
** __\ \/ /__/ __ |/ /__/ __ | http://www.scala-lang.org/ **
** /____/\___/_/ |_/____/_/ | | **
** |/ **
@@ -11,50 +11,62 @@ package collection
import convert._
-// TODO: I cleaned all this documentation up in JavaConversions, but the
-// documentation in here is basically the pre-cleaned-up version with minor
-// additions. Would be nice to have in one place.
-
-/** A collection of decorators that allow converting between
- * Scala and Java collections using `asScala` and `asJava` methods.
- *
- * The following conversions are supported via `asJava`, `asScala`
+/** A variety of decorators that enable converting between
+ * Scala and Java collections using extension methods, `asScala` and `asJava`.
*
- * - `scala.collection.Iterable` <=> `java.lang.Iterable`
- * - `scala.collection.Iterator` <=> `java.util.Iterator`
- * - `scala.collection.mutable.Buffer` <=> `java.util.List`
- * - `scala.collection.mutable.Set` <=> `java.util.Set`
- * - `scala.collection.mutable.Map` <=> `java.util.Map`
- * - `scala.collection.mutable.concurrent.Map` <=> `java.util.concurrent.ConcurrentMap`
+ * The extension methods return adapters for the corresponding API.
*
+ * The following conversions are supported via `asScala` and `asJava`:
+ *{{{
+ * scala.collection.Iterable <=> java.lang.Iterable
+ * scala.collection.Iterator <=> java.util.Iterator
+ * scala.collection.mutable.Buffer <=> java.util.List
+ * scala.collection.mutable.Set <=> java.util.Set
+ * scala.collection.mutable.Map <=> java.util.Map
+ * scala.collection.concurrent.Map <=> java.util.concurrent.ConcurrentMap
+ *}}}
+ * The following conversions are supported via `asScala` and through
+ * specially-named extension methods to convert to Java collections, as shown:
+ *{{{
+ * scala.collection.Iterable <=> java.util.Collection (via asJavaCollection)
+ * scala.collection.Iterator <=> java.util.Enumeration (via asJavaEnumeration)
+ * scala.collection.mutable.Map <=> java.util.Dictionary (via asJavaDictionary)
+ *}}}
+ * In addition, the following one-way conversions are provided via `asJava`:
+ *{{{
+ * scala.collection.Seq => java.util.List
+ * scala.collection.mutable.Seq => java.util.List
+ * scala.collection.Set => java.util.Set
+ * scala.collection.Map => java.util.Map
+ *}}}
+ * The following one way conversion is provided via `asScala`:
+ *{{{
+ * java.util.Properties => scala.collection.mutable.Map
+ *}}}
* In all cases, converting from a source type to a target type and back
- * again will return the original source object, e.g.
+ * again will return the original source object. For example:
* {{{
* import scala.collection.JavaConverters._
*
- * val sl = new scala.collection.mutable.ListBuffer[Int]
- * val jl : java.util.List[Int] = sl.asJava
- * val sl2 : scala.collection.mutable.Buffer[Int] = jl.asScala
- * assert(sl eq sl2)
+ * val source = new scala.collection.mutable.ListBuffer[Int]
+ * val target: java.util.List[Int] = source.asJava
+ * val other: scala.collection.mutable.Buffer[Int] = target.asScala
+ * assert(source eq other)
* }}}
- * The following conversions are also supported, but the
- * direction from Scala to Java is done by the more specifically named methods:
- * `asJavaCollection`, `asJavaEnumeration`, `asJavaDictionary`.
- *
- * - `scala.collection.Iterable` <=> `java.util.Collection`
- * - `scala.collection.Iterator` <=> `java.util.Enumeration`
- * - `scala.collection.mutable.Map` <=> `java.util.Dictionary`
- *
- * In addition, the following one way conversions are provided via `asJava`:
+ * Alternatively, the conversion methods have descriptive names and can be invoked explicitly.
+ * {{{
+ * scala> val vs = java.util.Arrays.asList("hi", "bye")
+ * vs: java.util.List[String] = [hi, bye]
*
- * - `scala.collection.Seq` => `java.util.List`
- * - `scala.collection.mutable.Seq` => `java.util.List`
- * - `scala.collection.Set` => `java.util.Set`
- * - `scala.collection.Map` => `java.util.Map`
+ * scala> val ss = asScalaIterator(vs.iterator)
+ * ss: Iterator[String] = non-empty iterator
*
- * The following one way conversion is provided via `asScala`:
+ * scala> .toList
+ * res0: List[String] = List(hi, bye)
*
- * - `java.util.Properties` => `scala.collection.mutable.Map`
+ * scala> val ss = asScalaBuffer(vs)
+ * ss: scala.collection.mutable.Buffer[String] = Buffer(hi, bye)
+ * }}}
*
* @since 2.8.1
*/
diff --git a/src/library/scala/collection/LinearSeqOptimized.scala b/src/library/scala/collection/LinearSeqOptimized.scala
index b7af8840a9..68b85dcfe5 100644
--- a/src/library/scala/collection/LinearSeqOptimized.scala
+++ b/src/library/scala/collection/LinearSeqOptimized.scala
@@ -9,8 +9,6 @@
package scala
package collection
-import mutable.ListBuffer
-import immutable.List
import scala.annotation.tailrec
/** A template trait for linear sequences of type `LinearSeq[A]` which optimizes
@@ -133,9 +131,9 @@ trait LinearSeqOptimized[+A, +Repr <: LinearSeqOptimized[A, Repr]] extends Linea
else op(head, tail.foldRight(z)(op))
override /*TraversableLike*/
- def reduceLeft[B >: A](f: (B, A) => B): B =
+ def reduceLeft[B >: A](@deprecatedName('f) op: (B, A) => B): B =
if (isEmpty) throw new UnsupportedOperationException("empty.reduceLeft")
- else tail.foldLeft[B](head)(f)
+ else tail.foldLeft[B](head)(op)
override /*IterableLike*/
def reduceRight[B >: A](op: (A, B) => B): B =
@@ -293,7 +291,7 @@ trait LinearSeqOptimized[+A, +Repr <: LinearSeqOptimized[A, Repr]] extends Linea
override /*SeqLike*/
def indexWhere(p: A => Boolean, from: Int): Int = {
- var i = from
+ var i = math.max(from, 0)
var these = this drop from
while (these.nonEmpty) {
if (p(these.head))
diff --git a/src/library/scala/collection/Map.scala b/src/library/scala/collection/Map.scala
index 1e40fd8c24..c9a943f1f7 100644
--- a/src/library/scala/collection/Map.scala
+++ b/src/library/scala/collection/Map.scala
@@ -12,7 +12,7 @@ package collection
import generic._
/**
- * A map from keys of type `A` to values of type `B`.
+ * A map from keys of type `K` to values of type `V`.
*
* $mapNote
*
@@ -22,15 +22,15 @@ import generic._
* '''Note:''' If your additions and mutations return the same kind of map as the map
* you are defining, you should inherit from `MapLike` as well.
*
- * @tparam A the type of the keys in this map.
- * @tparam B the type of the values associated with keys.
+ * @tparam K the type of the keys in this map.
+ * @tparam V the type of the values associated with keys.
*
* @since 1.0
*/
-trait Map[A, +B] extends Iterable[(A, B)] with GenMap[A, B] with MapLike[A, B, Map[A, B]] {
- def empty: Map[A, B] = Map.empty
+trait Map[K, +V] extends Iterable[(K, V)] with GenMap[K, V] with MapLike[K, V, Map[K, V]] {
+ def empty: Map[K, V] = Map.empty
- override def seq: Map[A, B] = this
+ override def seq: Map[K, V] = this
}
/** $factoryInfo
@@ -38,22 +38,22 @@ trait Map[A, +B] extends Iterable[(A, B)] with GenMap[A, B] with MapLike[A, B, M
* @define coll map
*/
object Map extends MapFactory[Map] {
- def empty[A, B]: immutable.Map[A, B] = immutable.Map.empty
+ def empty[K, V]: immutable.Map[K, V] = immutable.Map.empty
/** $mapCanBuildFromInfo */
- implicit def canBuildFrom[A, B]: CanBuildFrom[Coll, (A, B), Map[A, B]] = new MapCanBuildFrom[A, B]
+ implicit def canBuildFrom[K, V]: CanBuildFrom[Coll, (K, V), Map[K, V]] = new MapCanBuildFrom[K, V]
/** An abstract shell used by { mutable, immutable }.Map but not by collection.Map
* because of variance issues.
*/
- abstract class WithDefault[A, +B](underlying: Map[A, B], d: A => B) extends AbstractMap[A, B] with Map[A, B] with Serializable {
+ abstract class WithDefault[K, +V](underlying: Map[K, V], d: K => V) extends AbstractMap[K, V] with Map[K, V] with Serializable {
override def size = underlying.size
- def get(key: A) = underlying.get(key) // removed in 2.9: orElse Some(default(key))
+ def get(key: K) = underlying.get(key) // removed in 2.9: orElse Some(default(key))
def iterator = underlying.iterator
- override def default(key: A): B = d(key)
+ override def default(key: K): V = d(key)
}
}
/** Explicit instantiation of the `Map` trait to reduce class file size in subclasses. */
-abstract class AbstractMap[A, +B] extends AbstractIterable[(A, B)] with Map[A, B]
+abstract class AbstractMap[K, +V] extends AbstractIterable[(K, V)] with Map[K, V]
diff --git a/src/library/scala/collection/MapLike.scala b/src/library/scala/collection/MapLike.scala
index 99ed67325c..a087cb0f45 100644
--- a/src/library/scala/collection/MapLike.scala
+++ b/src/library/scala/collection/MapLike.scala
@@ -11,7 +11,7 @@ package collection
import generic._
import mutable.{ Builder, MapBuilder }
-import scala.annotation.{migration, bridge}
+import scala.annotation.migration
import parallel.ParMap
/** A template trait for maps, which associate keys with values.
@@ -28,10 +28,10 @@ import parallel.ParMap
* To implement a concrete map, you need to provide implementations of the
* following methods:
* {{{
- * def get(key: A): Option[B]
- * def iterator: Iterator[(A, B)]
- * def + [B1 >: B](kv: (A, B1)): This
- * def -(key: A): This
+ * def get(key: K): Option[V]
+ * def iterator: Iterator[(K, V)]
+ * def + [V1 >: V](kv: (K, V1)): This
+ * def -(key: K): This
* }}}
* If you wish that methods like `take`, `drop`, `filter` also return the same kind of map
* you should also override:
@@ -42,8 +42,8 @@ import parallel.ParMap
* `size` for efficiency.
*
* @define mapTags
- * @tparam A the type of the keys.
- * @tparam B the type of associated values.
+ * @tparam K the type of the keys.
+ * @tparam V the type of associated values.
* @tparam This the type of the map itself.
*
* @author Martin Odersky
@@ -54,12 +54,12 @@ import parallel.ParMap
* @define willNotTerminateInf
* @define mayNotTerminateInf
*/
-trait MapLike[A, +B, +This <: MapLike[A, B, This] with Map[A, B]]
- extends PartialFunction[A, B]
- with IterableLike[(A, B), This]
- with GenMapLike[A, B, This]
- with Subtractable[A, This]
- with Parallelizable[(A, B), ParMap[A, B]]
+trait MapLike[K, +V, +This <: MapLike[K, V, This] with Map[K, V]]
+ extends PartialFunction[K, V]
+ with IterableLike[(K, V), This]
+ with GenMapLike[K, V, This]
+ with Subtractable[K, This]
+ with Parallelizable[(K, V), ParMap[K, V]]
{
self =>
@@ -71,7 +71,7 @@ self =>
/** A common implementation of `newBuilder` for all maps in terms of `empty`.
* Overridden for mutable maps in `mutable.MapLike`.
*/
- override protected[this] def newBuilder: Builder[(A, B), This] = new MapBuilder[A, B, This](empty)
+ override protected[this] def newBuilder: Builder[(K, V), This] = new MapBuilder[K, V, This](empty)
/** Optionally returns the value associated with a key.
*
@@ -79,32 +79,32 @@ self =>
* @return an option value containing the value associated with `key` in this map,
* or `None` if none exists.
*/
- def get(key: A): Option[B]
+ def get(key: K): Option[V]
/** Creates a new iterator over all key/value pairs of this map
*
* @return the new iterator
*/
- def iterator: Iterator[(A, B)]
+ def iterator: Iterator[(K, V)]
/** Adds a key/value pair to this map, returning a new map.
* @param kv the key/value pair
- * @tparam B1 the type of the value in the key/value pair.
+ * @tparam V1 the type of the value in the key/value pair.
* @return a new map with the new binding added to this map
*
- * @usecase def + (kv: (A, B)): Map[A, B]
+ * @usecase def + (kv: (K, V)): Map[K, V]
* @inheritdoc
*/
- def + [B1 >: B] (kv: (A, B1)): Map[A, B1]
+ def + [V1 >: V] (kv: (K, V1)): Map[K, V1]
/** Removes a key from this map, returning a new map.
* @param key the key to be removed
* @return a new map without a binding for `key`
*
- * @usecase def - (key: A): Map[A, B]
+ * @usecase def - (key: K): Map[K, V]
* @inheritdoc
*/
- def - (key: A): This
+ def - (key: K): This
/** Tests whether the map is empty.
*
@@ -116,14 +116,14 @@ self =>
* @param key the key.
* @param default a computation that yields a default value in case no binding for `key` is
* found in the map.
- * @tparam B1 the result type of the default computation.
+ * @tparam V1 the result type of the default computation.
* @return the value associated with `key` if it exists,
* otherwise the result of the `default` computation.
*
- * @usecase def getOrElse(key: A, default: => B): B
+ * @usecase def getOrElse(key: K, default: => V): V
* @inheritdoc
*/
- def getOrElse[B1 >: B](key: A, default: => B1): B1 = get(key) match {
+ def getOrElse[V1 >: V](key: K, default: => V1): V1 = get(key) match {
case Some(v) => v
case None => default
}
@@ -137,7 +137,7 @@ self =>
* @return the value associated with the given key, or the result of the
* map's `default` method, if none exists.
*/
- def apply(key: A): B = get(key) match {
+ def apply(key: K): V = get(key) match {
case None => default(key)
case Some(value) => value
}
@@ -147,7 +147,7 @@ self =>
* @param key the key
* @return `true` if there is a binding for `key` in this map, `false` otherwise.
*/
- def contains(key: A): Boolean = get(key).isDefined
+ def contains(key: K): Boolean = get(key).isDefined
/** Tests whether this map contains a binding for a key. This method,
* which implements an abstract method of trait `PartialFunction`,
@@ -156,29 +156,33 @@ self =>
* @param key the key
* @return `true` if there is a binding for `key` in this map, `false` otherwise.
*/
- def isDefinedAt(key: A) = contains(key)
+ def isDefinedAt(key: K) = contains(key)
+
+ override /*PartialFunction*/
+ def applyOrElse[K1 <: K, V1 >: V](x: K1, default: K1 => V1): V1 =
+ getOrElse(x, default(x))
/** Collects all keys of this map in a set.
* @return a set containing all keys of this map.
*/
- def keySet: Set[A] = new DefaultKeySet
+ def keySet: Set[K] = new DefaultKeySet
/** The implementation class of the set returned by `keySet`.
*/
- protected class DefaultKeySet extends AbstractSet[A] with Set[A] with Serializable {
- def contains(key : A) = self.contains(key)
+ protected class DefaultKeySet extends AbstractSet[K] with Set[K] with Serializable {
+ def contains(key : K) = self.contains(key)
def iterator = keysIterator
- def + (elem: A): Set[A] = (Set[A]() ++ this + elem).asInstanceOf[Set[A]] // !!! concrete overrides abstract problem
- def - (elem: A): Set[A] = (Set[A]() ++ this - elem).asInstanceOf[Set[A]] // !!! concrete overrides abstract problem
+ def + (elem: K): Set[K] = (Set[K]() ++ this + elem).asInstanceOf[Set[K]] // !!! concrete overrides abstract problem
+ def - (elem: K): Set[K] = (Set[K]() ++ this - elem).asInstanceOf[Set[K]] // !!! concrete overrides abstract problem
override def size = self.size
- override def foreach[U](f: A => U) = self.keysIterator foreach f
+ override def foreach[U](f: K => U) = self.keysIterator foreach f
}
/** Creates an iterator for all keys.
*
* @return an iterator over all keys.
*/
- def keysIterator: Iterator[A] = new AbstractIterator[A] {
+ def keysIterator: Iterator[K] = new AbstractIterator[K] {
val iter = self.iterator
def hasNext = iter.hasNext
def next() = iter.next()._1
@@ -188,29 +192,29 @@ self =>
*
* @return the keys of this map as an iterable.
*/
- @migration("`keys` returns `Iterable[A]` rather than `Iterator[A]`.", "2.8.0")
- def keys: Iterable[A] = keySet
+ @migration("`keys` returns `Iterable[K]` rather than `Iterator[K]`.", "2.8.0")
+ def keys: Iterable[K] = keySet
/** Collects all values of this map in an iterable collection.
*
* @return the values of this map as an iterable.
*/
- @migration("`values` returns `Iterable[B]` rather than `Iterator[B]`.", "2.8.0")
- def values: Iterable[B] = new DefaultValuesIterable
+ @migration("`values` returns `Iterable[V]` rather than `Iterator[V]`.", "2.8.0")
+ def values: Iterable[V] = new DefaultValuesIterable
/** The implementation class of the iterable returned by `values`.
*/
- protected class DefaultValuesIterable extends AbstractIterable[B] with Iterable[B] with Serializable {
+ protected class DefaultValuesIterable extends AbstractIterable[V] with Iterable[V] with Serializable {
def iterator = valuesIterator
override def size = self.size
- override def foreach[U](f: B => U) = self.valuesIterator foreach f
+ override def foreach[U](f: V => U) = self.valuesIterator foreach f
}
/** Creates an iterator for all values in this map.
*
* @return an iterator over all values that are associated with some key in this map.
*/
- def valuesIterator: Iterator[B] = new AbstractIterator[B] {
+ def valuesIterator: Iterator[V] = new AbstractIterator[V] {
val iter = self.iterator
def hasNext = iter.hasNext
def next() = iter.next()._2
@@ -224,29 +228,33 @@ self =>
* @param key the given key value for which a binding is missing.
* @throws NoSuchElementException
*/
- def default(key: A): B =
+ def default(key: K): V =
throw new NoSuchElementException("key not found: " + key)
- protected class FilteredKeys(p: A => Boolean) extends AbstractMap[A, B] with DefaultMap[A, B] {
- override def foreach[U](f: ((A, B)) => U): Unit = for (kv <- self) if (p(kv._1)) f(kv)
+ protected class FilteredKeys(p: K => Boolean) extends AbstractMap[K, V] with DefaultMap[K, V] {
+ override def foreach[U](f: ((K, V)) => U): Unit = for (kv <- self) if (p(kv._1)) f(kv)
def iterator = self.iterator.filter(kv => p(kv._1))
- override def contains(key: A) = self.contains(key) && p(key)
- def get(key: A) = if (!p(key)) None else self.get(key)
+ override def contains(key: K) = p(key) && self.contains(key)
+ def get(key: K) = if (!p(key)) None else self.get(key)
}
/** Filters this map by retaining only keys satisfying a predicate.
+ *
+ * '''Note''': the predicate must accept any key of type `K`, not just those already
+ * present in the map, as the predicate is tested before the underlying map is queried.
+ *
* @param p the predicate used to test keys
* @return an immutable map consisting only of those key value pairs of this map where the key satisfies
* the predicate `p`. The resulting map wraps the original map without copying any elements.
*/
- def filterKeys(p: A => Boolean): Map[A, B] = new FilteredKeys(p)
+ def filterKeys(p: K => Boolean): Map[K, V] = new FilteredKeys(p)
- protected class MappedValues[C](f: B => C) extends AbstractMap[A, C] with DefaultMap[A, C] {
- override def foreach[U](g: ((A, C)) => U): Unit = for ((k, v) <- self) g((k, f(v)))
+ protected class MappedValues[W](f: V => W) extends AbstractMap[K, W] with DefaultMap[K, W] {
+ override def foreach[U](g: ((K, W)) => U): Unit = for ((k, v) <- self) g((k, f(v)))
def iterator = for ((k, v) <- self.iterator) yield (k, f(v))
override def size = self.size
- override def contains(key: A) = self.contains(key)
- def get(key: A) = self.get(key).map(f)
+ override def contains(key: K) = self.contains(key)
+ def get(key: K) = self.get(key).map(f)
}
/** Transforms this map by applying a function to every retrieved value.
@@ -254,22 +262,22 @@ self =>
* @return a map view which maps every key of this map
* to `f(this(key))`. The resulting map wraps the original map without copying any elements.
*/
- def mapValues[C](f: B => C): Map[A, C] = new MappedValues(f)
+ def mapValues[W](f: V => W): Map[K, W] = new MappedValues(f)
// The following 5 operations (updated, two times +, two times ++) should really be
- // generic, returning This[B]. We need better covariance support to express that though.
+ // generic, returning This[V]. We need better covariance support to express that though.
// So right now we do the brute force approach of code duplication.
/** Creates a new map obtained by updating this map with a given key/value pair.
* @param key the key
* @param value the value
- * @tparam B1 the type of the added value
+ * @tparam V1 the type of the added value
* @return A new map with the new key/value mapping added to this map.
*
- * @usecase def updated(key: A, value: B): Map[A, B]
+ * @usecase def updated(key: K, value: V): Map[K, V]
* @inheritdoc
*/
- def updated [B1 >: B](key: A, value: B1): Map[A, B1] = this + ((key, value))
+ def updated [V1 >: V](key: K, value: V1): Map[K, V1] = this + ((key, value))
/** Adds key/value pairs to this map, returning a new map.
*
@@ -279,27 +287,27 @@ self =>
* @param kv1 the first key/value pair
* @param kv2 the second key/value pair
* @param kvs the remaining key/value pairs
- * @tparam B1 the type of the added values
+ * @tparam V1 the type of the added values
* @return a new map with the given bindings added to this map
*
- * @usecase def + (kvs: (A, B)*): Map[A, B]
+ * @usecase def + (kvs: (K, V)*): Map[K, V]
* @inheritdoc
* @param kvs the key/value pairs
*/
- def + [B1 >: B] (kv1: (A, B1), kv2: (A, B1), kvs: (A, B1) *): Map[A, B1] =
+ def + [V1 >: V] (kv1: (K, V1), kv2: (K, V1), kvs: (K, V1) *): Map[K, V1] =
this + kv1 + kv2 ++ kvs
/** Adds all key/value pairs in a traversable collection to this map, returning a new map.
*
* @param xs the collection containing the added key/value pairs
- * @tparam B1 the type of the added values
+ * @tparam V1 the type of the added values
* @return a new map with the given bindings added to this map
*
- * @usecase def ++ (xs: Traversable[(A, B)]): Map[A, B]
+ * @usecase def ++ (xs: Traversable[(K, V)]): Map[K, V]
* @inheritdoc
*/
- def ++[B1 >: B](xs: GenTraversableOnce[(A, B1)]): Map[A, B1] =
- ((repr: Map[A, B1]) /: xs.seq) (_ + _)
+ def ++[V1 >: V](xs: GenTraversableOnce[(K, V1)]): Map[K, V1] =
+ ((repr: Map[K, V1]) /: xs.seq) (_ + _)
/** Returns a new map obtained by removing all key/value pairs for which the predicate
* `p` returns `true`.
@@ -312,22 +320,31 @@ self =>
* @param p A predicate over key-value pairs
* @return A new map containing elements not satisfying the predicate.
*/
- override def filterNot(p: ((A, B)) => Boolean): This = {
+ override def filterNot(p: ((K, V)) => Boolean): This = {
var res: This = repr
for (kv <- this)
if (p(kv)) res = (res - kv._1).asInstanceOf[This] // !!! concrete overrides abstract problem
res
}
- /* Overridden for efficiency. */
- override def toSeq: Seq[(A, B)] = toBuffer[(A, B)]
- override def toBuffer[C >: (A, B)]: mutable.Buffer[C] = {
- val result = new mutable.ArrayBuffer[C](size)
- copyToBuffer(result)
+ override def toSeq: Seq[(K, V)] = {
+ if (isEmpty) Vector.empty[(K, V)]
+ else {
+ // Default appropriate for immutable collections; mutable collections override this
+ val vb = Vector.newBuilder[(K, V)]
+ foreach(vb += _)
+ vb.result
+ }
+ }
+
+ override def toBuffer[E >: (K, V)]: mutable.Buffer[E] = {
+ val result = new mutable.ArrayBuffer[E](size)
+ // Faster to let the map iterate itself than to defer through copyToBuffer
+ foreach(result += _)
result
}
- protected[this] override def parCombiner = ParMap.newCombiner[A, B]
+ protected[this] override def parCombiner = ParMap.newCombiner[K, V]
/** Appends all bindings of this map to a string builder using start, end, and separator strings.
* The written text begins with the string `start` and ends with the string
diff --git a/src/library/scala/collection/MapProxy.scala b/src/library/scala/collection/MapProxy.scala
index 26a7c710ee..2faf689973 100644
--- a/src/library/scala/collection/MapProxy.scala
+++ b/src/library/scala/collection/MapProxy.scala
@@ -17,5 +17,5 @@ package collection
* @version 1.0, 21/07/2003
* @since 1
*/
-@deprecated("Proxying is deprecated due to lack of use and compiler-level support.", "2.11.3")
+@deprecated("proxying is deprecated due to lack of use and compiler-level support", "2.11.3")
trait MapProxy[A, +B] extends Map[A, B] with MapProxyLike[A, B, Map[A, B]]
diff --git a/src/library/scala/collection/MapProxyLike.scala b/src/library/scala/collection/MapProxyLike.scala
index dd80a538e3..73a6935788 100644
--- a/src/library/scala/collection/MapProxyLike.scala
+++ b/src/library/scala/collection/MapProxyLike.scala
@@ -18,7 +18,7 @@ package collection
* @version 2.8
* @since 2.8
*/
-@deprecated("Proxying is deprecated due to lack of use and compiler-level support.", "2.11.0")
+@deprecated("proxying is deprecated due to lack of use and compiler-level support", "2.11.0")
trait MapProxyLike[A, +B, +This <: MapLike[A, B, This] with Map[A, B]]
extends MapLike[A, B, This]
with IterableProxyLike[(A, B), This]
diff --git a/src/library/scala/collection/Parallelizable.scala b/src/library/scala/collection/Parallelizable.scala
index b737752458..c131556388 100644
--- a/src/library/scala/collection/Parallelizable.scala
+++ b/src/library/scala/collection/Parallelizable.scala
@@ -12,7 +12,7 @@ package collection
import parallel.Combiner
/** This trait describes collections which can be turned into parallel collections
- * by invoking the method `par`. Parallelizable collections may be parametrized with
+ * by invoking the method `par`. Parallelizable collections may be parameterized with
* a target type different than their own.
*
* @tparam A the type of the elements in the collection
diff --git a/src/library/scala/collection/SeqLike.scala b/src/library/scala/collection/SeqLike.scala
index b775480532..3e025bc43f 100644
--- a/src/library/scala/collection/SeqLike.scala
+++ b/src/library/scala/collection/SeqLike.scala
@@ -9,11 +9,10 @@
package scala
package collection
-import mutable.{ ListBuffer, ArraySeq }
import immutable.{ List, Range }
import generic._
import parallel.ParSeq
-import scala.math.{ min, max, Ordering }
+import scala.math.Ordering
/** A template trait for sequences of type `Seq[A]`
* $seqInfo
@@ -114,13 +113,12 @@ trait SeqLike[+A, +Repr] extends Any with IterableLike[A, Repr] with GenSeqLike[
}
def indexWhere(p: A => Boolean, from: Int): Int = {
- var i = from
+ var i = math.max(from, 0)
val it = iterator.drop(from)
while (it.hasNext) {
if (p(it.next())) return i
else i += 1
}
-
-1
}
@@ -146,7 +144,7 @@ trait SeqLike[+A, +Repr] extends Any with IterableLike[A, Repr] with GenSeqLike[
* more than one way to generate the same subsequence, only one will be returned.
*
* For example, `"xyyy"` has three different ways to generate `"xy"` depending on
- * whether the first, second, or third `"y"` is selected. However, since all are
+ * whether the first, second, or third `"y"` is selected. However, since all are
* identical, only one will be chosen. Which of the three will be taken is an
* implementation detail that is not defined.
*
diff --git a/src/library/scala/collection/SeqProxy.scala b/src/library/scala/collection/SeqProxy.scala
index f728ba8585..f2b39c7b55 100644
--- a/src/library/scala/collection/SeqProxy.scala
+++ b/src/library/scala/collection/SeqProxy.scala
@@ -18,5 +18,5 @@ package collection
* @version 2.8
* @since 2.8
*/
-@deprecated("Proxying is deprecated due to lack of use and compiler-level support.", "2.11.0")
+@deprecated("proxying is deprecated due to lack of use and compiler-level support", "2.11.0")
trait SeqProxy[+A] extends Seq[A] with SeqProxyLike[A, Seq[A]]
diff --git a/src/library/scala/collection/SeqProxyLike.scala b/src/library/scala/collection/SeqProxyLike.scala
index b01d227d10..b493c70796 100644
--- a/src/library/scala/collection/SeqProxyLike.scala
+++ b/src/library/scala/collection/SeqProxyLike.scala
@@ -23,7 +23,7 @@ import generic._
* @version 2.8
* @since 2.8
*/
-@deprecated("Proxying is deprecated due to lack of use and compiler-level support.", "2.11.0")
+@deprecated("proxying is deprecated due to lack of use and compiler-level support", "2.11.0")
trait SeqProxyLike[+A, +Repr <: SeqLike[A, Repr] with Seq[A]] extends SeqLike[A, Repr] with IterableProxyLike[A, Repr] {
override def size = self.size
override def toSeq: Seq[A] = self.toSeq
diff --git a/src/library/scala/collection/SeqViewLike.scala b/src/library/scala/collection/SeqViewLike.scala
index 3473c8aff1..1fbcb6531e 100644
--- a/src/library/scala/collection/SeqViewLike.scala
+++ b/src/library/scala/collection/SeqViewLike.scala
@@ -96,6 +96,14 @@ trait SeqViewLike[+A,
if (idx < self.length) self(idx) else restSeq(idx - self.length)
}
+ trait Prepended[B >: A] extends super.Prepended[B] with Transformed[B] {
+ protected[this] lazy val fstSeq = fst.toSeq
+ def length: Int = fstSeq.length + self.length
+ def apply(idx: Int): B =
+ if (idx < fstSeq.length) fstSeq(idx)
+ else self.apply(idx - fstSeq.length)
+ }
+
trait Filtered extends super.Filtered with Transformed[A] {
protected[this] lazy val index = {
var len = 0
@@ -179,21 +187,12 @@ trait SeqViewLike[+A,
final override protected[this] def viewIdentifier = "P"
}
- trait Prepended[B >: A] extends Transformed[B] {
- protected[this] val fst: B
- override def iterator: Iterator[B] = Iterator.single(fst) ++ self.iterator
- def length: Int = 1 + self.length
- def apply(idx: Int): B =
- if (idx == 0) fst
- else self.apply(idx - 1)
- final override protected[this] def viewIdentifier = "A"
- }
-
/** Boilerplate method, to override in each subclass
* This method could be eliminated if Scala had virtual classes
*/
protected override def newForced[B](xs: => GenSeq[B]): Transformed[B] = new { val forced = xs } with AbstractTransformed[B] with Forced[B]
protected override def newAppended[B >: A](that: GenTraversable[B]): Transformed[B] = new { val rest = that } with AbstractTransformed[B] with Appended[B]
+ protected override def newPrepended[B >: A](that: GenTraversable[B]): Transformed[B] = new { protected[this] val fst = that } with AbstractTransformed[B] with Prepended[B]
protected override def newMapped[B](f: A => B): Transformed[B] = new { val mapping = f } with AbstractTransformed[B] with Mapped[B]
protected override def newFlatMapped[B](f: A => GenTraversableOnce[B]): Transformed[B] = new { val mapping = f } with AbstractTransformed[B] with FlatMapped[B]
protected override def newFiltered(p: A => Boolean): Transformed[A] = new { val pred = p } with AbstractTransformed[A] with Filtered
@@ -212,7 +211,6 @@ trait SeqViewLike[+A,
val patch = _patch
val replaced = _replaced
} with AbstractTransformed[B] with Patched[B]
- protected def newPrepended[B >: A](elem: B): Transformed[B] = new { protected[this] val fst = elem } with AbstractTransformed[B] with Prepended[B]
// see comment in IterableViewLike.
protected override def newTaken(n: Int): Transformed[A] = newSliced(SliceInterval(0, n))
@@ -242,7 +240,7 @@ trait SeqViewLike[+A,
}
override def +:[B >: A, That](elem: B)(implicit bf: CanBuildFrom[This, B, That]): That =
- newPrepended(elem).asInstanceOf[That]
+ newPrepended(elem :: Nil).asInstanceOf[That]
override def :+[B >: A, That](elem: B)(implicit bf: CanBuildFrom[This, B, That]): That =
++(Iterator.single(elem))(bf)
diff --git a/src/library/scala/collection/SetLike.scala b/src/library/scala/collection/SetLike.scala
index f8ac1d754d..440452ce99 100644
--- a/src/library/scala/collection/SetLike.scala
+++ b/src/library/scala/collection/SetLike.scala
@@ -11,7 +11,7 @@ package collection
import generic._
import mutable.{ Builder, SetBuilder }
-import scala.annotation.{migration, bridge}
+import scala.annotation.migration
import parallel.ParSet
/** A template trait for sets.
@@ -77,11 +77,20 @@ self =>
protected[this] override def parCombiner = ParSet.newCombiner[A]
- /* Overridden for efficiency. */
- override def toSeq: Seq[A] = toBuffer[A]
+ // Default collection type appropriate for immutable collections; mutable collections override this
+ override def toSeq: Seq[A] = {
+ if (isEmpty) Vector.empty[A]
+ else {
+ val vb = Vector.newBuilder[A]
+ foreach(vb += _)
+ vb.result
+ }
+ }
+
override def toBuffer[A1 >: A]: mutable.Buffer[A1] = {
val result = new mutable.ArrayBuffer[A1](size)
- copyToBuffer(result)
+ // Faster to let the map iterate itself than to defer through copyToBuffer
+ foreach(result += _)
result
}
@@ -204,9 +213,9 @@ self =>
}
}
- /** An Iterator include all subsets containing exactly len elements.
+ /** An Iterator including all subsets containing exactly len elements.
* If the elements in 'This' type is ordered, then the subsets will also be in the same order.
- * ListSet(1,2,3).subsets => {1},{2},{3},{1,2},{1,3},{2,3},{1,2,3}}
+ * ListSet(1,2,3).subsets => {{1},{2},{3},{1,2},{1,3},{2,3},{1,2,3}}
*
* @author Eastsun
* @date 2010.12.6
diff --git a/src/library/scala/collection/SetProxy.scala b/src/library/scala/collection/SetProxy.scala
index e17fb215b9..4a3fc17a78 100644
--- a/src/library/scala/collection/SetProxy.scala
+++ b/src/library/scala/collection/SetProxy.scala
@@ -17,5 +17,5 @@ package collection
* @author Martin Odersky
* @version 2.0, 01/01/2007
*/
-@deprecated("Proxying is deprecated due to lack of use and compiler-level support.", "2.11.3")
+@deprecated("proxying is deprecated due to lack of use and compiler-level support", "2.11.3")
trait SetProxy[A] extends Set[A] with SetProxyLike[A, Set[A]]
diff --git a/src/library/scala/collection/SetProxyLike.scala b/src/library/scala/collection/SetProxyLike.scala
index 4cd215cd89..fa23fe5450 100644
--- a/src/library/scala/collection/SetProxyLike.scala
+++ b/src/library/scala/collection/SetProxyLike.scala
@@ -17,7 +17,7 @@ package collection
* @author Martin Odersky
* @version 2.8
*/
-@deprecated("Proxying is deprecated due to lack of use and compiler-level support.", "2.11.0")
+@deprecated("proxying is deprecated due to lack of use and compiler-level support", "2.11.0")
trait SetProxyLike[A, +This <: SetLike[A, This] with Set[A]] extends SetLike[A, This] with IterableProxyLike[A, This] {
def empty: This
override def contains(elem: A): Boolean = self.contains(elem)
diff --git a/src/library/scala/collection/SortedSet.scala b/src/library/scala/collection/SortedSet.scala
index 43189d2e8c..0fa5ce0966 100644
--- a/src/library/scala/collection/SortedSet.scala
+++ b/src/library/scala/collection/SortedSet.scala
@@ -29,6 +29,6 @@ trait SortedSet[A] extends Set[A] with SortedSetLike[A, SortedSet[A]] {
object SortedSet extends SortedSetFactory[SortedSet] {
def empty[A](implicit ord: Ordering[A]): immutable.SortedSet[A] = immutable.SortedSet.empty[A](ord)
def canBuildFrom[A](implicit ord: Ordering[A]): CanBuildFrom[Coll, A, SortedSet[A]] = newCanBuildFrom[A]
- // Force a declaration here so that BitSet's (which does not inherit from SortedSetFactory) can be more specific
+ // Force a declaration here so that BitSet (which does not inherit from SortedSetFactory) can be more specific
override implicit def newCanBuildFrom[A](implicit ord : Ordering[A]) : CanBuildFrom[Coll, A, SortedSet[A]] = super.newCanBuildFrom
}
diff --git a/src/library/scala/collection/TraversableLike.scala b/src/library/scala/collection/TraversableLike.scala
index bbbc33b3f5..c9482fe0a2 100644
--- a/src/library/scala/collection/TraversableLike.scala
+++ b/src/library/scala/collection/TraversableLike.scala
@@ -11,7 +11,7 @@ package collection
import generic._
import mutable.{ Builder }
-import scala.annotation.{tailrec, migration, bridge}
+import scala.annotation.migration
import scala.annotation.unchecked.{ uncheckedVariance => uV }
import parallel.ParIterable
import scala.language.higherKinds
@@ -242,7 +242,7 @@ trait TraversableLike[+A, +Repr] extends Any
b.result
}
- private def filterImpl(p: A => Boolean, isFlipped: Boolean): Repr = {
+ private[scala] def filterImpl(p: A => Boolean, isFlipped: Boolean): Repr = {
val b = newBuilder
for (x <- this)
if (p(x) != isFlipped) b += x
@@ -605,13 +605,69 @@ trait TraversableLike[+A, +Repr] extends Any
* applied to this $coll. By default the string prefix is the
* simple name of the collection class $coll.
*/
- def stringPrefix : String = {
- var string = repr.getClass.getName
- val idx1 = string.lastIndexOf('.' : Int)
- if (idx1 != -1) string = string.substring(idx1 + 1)
- val idx2 = string.indexOf('$')
- if (idx2 != -1) string = string.substring(0, idx2)
- string
+ def stringPrefix: String = {
+ /* This method is written in a style that avoids calling `String.split()`
+ * as well as methods of java.lang.Character that require the Unicode
+ * database information. This is mostly important for Scala.js, so that
+ * using the collection library does automatically bring java.util.regex.*
+ * and the Unicode database in the generated code.
+ *
+ * This algorithm has the additional benefit that it won't allocate
+ * anything except the result String in the common case, where the class
+ * is not an inner class (i.e., when the result contains no '.').
+ */
+ val fqn = repr.getClass.getName
+ var pos: Int = fqn.length - 1
+
+ // Skip trailing $'s
+ while (pos != -1 && fqn.charAt(pos) == '$') {
+ pos -= 1
+ }
+ if (pos == -1 || fqn.charAt(pos) == '.') {
+ return ""
+ }
+
+ var result: String = ""
+ while (true) {
+ // Invariant: if we enter the loop, there is a non-empty part
+
+ // Look for the beginning of the part, remembering where was the last non-digit
+ val partEnd = pos + 1
+ while (pos != -1 && fqn.charAt(pos) <= '9' && fqn.charAt(pos) >= '0') {
+ pos -= 1
+ }
+ val lastNonDigit = pos
+ while (pos != -1 && fqn.charAt(pos) != '$' && fqn.charAt(pos) != '.') {
+ pos -= 1
+ }
+ val partStart = pos + 1
+
+ // A non-last part which contains only digits marks a method-local part -> drop the prefix
+ if (pos == lastNonDigit && partEnd != fqn.length) {
+ return result
+ }
+
+ // Skip to the next part, and determine whether we are the end
+ while (pos != -1 && fqn.charAt(pos) == '$') {
+ pos -= 1
+ }
+ val atEnd = pos == -1 || fqn.charAt(pos) == '.'
+
+ // Handle the actual content of the part (we ignore parts that are likely synthetic)
+ def isPartLikelySynthetic = {
+ val firstChar = fqn.charAt(partStart)
+ (firstChar > 'Z' && firstChar < 0x7f) || (firstChar < 'A')
+ }
+ if (atEnd || !isPartLikelySynthetic) {
+ val part = fqn.substring(partStart, partEnd)
+ result = if (result.isEmpty) part else part + '.' + result
+ if (atEnd)
+ return result
+ }
+ }
+
+ // dead code
+ result
}
/** Creates a non-strict view of this $coll.
diff --git a/src/library/scala/collection/TraversableOnce.scala b/src/library/scala/collection/TraversableOnce.scala
index 75c0d82922..b87fcd166e 100644
--- a/src/library/scala/collection/TraversableOnce.scala
+++ b/src/library/scala/collection/TraversableOnce.scala
@@ -9,7 +9,7 @@
package scala
package collection
-import mutable.{ Buffer, Builder, ListBuffer, ArrayBuffer }
+import mutable.{ Buffer, Builder, ArrayBuffer }
import generic.CanBuildFrom
import scala.annotation.unchecked.{ uncheckedVariance => uV }
import scala.language.{implicitConversions, higherKinds}
diff --git a/src/library/scala/collection/TraversableProxy.scala b/src/library/scala/collection/TraversableProxy.scala
index 9eec685d10..0c7219c5f9 100644
--- a/src/library/scala/collection/TraversableProxy.scala
+++ b/src/library/scala/collection/TraversableProxy.scala
@@ -21,5 +21,5 @@ package collection
* @version 2.8
* @since 2.8
*/
-@deprecated("Proxying is deprecated due to lack of use and compiler-level support.", "2.11.3")
+@deprecated("proxying is deprecated due to lack of use and compiler-level support", "2.11.3")
trait TraversableProxy[+A] extends Traversable[A] with TraversableProxyLike[A, Traversable[A]]
diff --git a/src/library/scala/collection/TraversableProxyLike.scala b/src/library/scala/collection/TraversableProxyLike.scala
index fa470ea238..c8b641f88b 100644
--- a/src/library/scala/collection/TraversableProxyLike.scala
+++ b/src/library/scala/collection/TraversableProxyLike.scala
@@ -24,7 +24,7 @@ import scala.reflect.ClassTag
* @version 2.8
* @since 2.8
*/
-@deprecated("Proxying is deprecated due to lack of use and compiler-level support.", "2.11.0")
+@deprecated("proxying is deprecated due to lack of use and compiler-level support", "2.11.0")
trait TraversableProxyLike[+A, +Repr <: TraversableLike[A, Repr] with Traversable[A]] extends TraversableLike[A, Repr] with Proxy {
def self: Repr
diff --git a/src/library/scala/collection/TraversableViewLike.scala b/src/library/scala/collection/TraversableViewLike.scala
index 5926c69ebf..0901d749c3 100644
--- a/src/library/scala/collection/TraversableViewLike.scala
+++ b/src/library/scala/collection/TraversableViewLike.scala
@@ -189,6 +189,15 @@ trait TraversableViewLike[+A,
}
final override protected[this] def viewIdentifier = "A"
}
+
+ trait Prepended[B >: A] extends Transformed[B] {
+ protected[this] val fst: GenTraversable[B]
+ def foreach[U](f: B => U) {
+ fst foreach f
+ self foreach f
+ }
+ final override protected[this] def viewIdentifier = "A"
+ }
trait Filtered extends Transformed[A] {
protected[this] val pred: A => Boolean
@@ -222,11 +231,15 @@ trait TraversableViewLike[+A,
final override protected[this] def viewIdentifier = "D"
}
- override def ++[B >: A, That](xs: GenTraversableOnce[B])(implicit bf: CanBuildFrom[This, B, That]): That = {
+ override def ++[B >: A, That](xs: GenTraversableOnce[B])(implicit bf: CanBuildFrom[This, B, That]): That =
newAppended(xs.seq.toTraversable).asInstanceOf[That]
-// was: if (bf.isInstanceOf[ByPassCanBuildFrom]) newAppended(that).asInstanceOf[That]
-// else super.++[B, That](that)(bf)
- }
+
+ override def ++:[B >: A, That](xs: TraversableOnce[B])(implicit bf: CanBuildFrom[This, B, That]): That =
+ newPrepended(xs.seq.toTraversable).asInstanceOf[That]
+
+ // Need second one because of optimization in TraversableLike
+ override def ++:[B >: A, That](xs: Traversable[B])(implicit bf: CanBuildFrom[This, B, That]): That =
+ newPrepended(xs).asInstanceOf[That]
override def map[B, That](f: A => B)(implicit bf: CanBuildFrom[This, B, That]): That = {
newMapped(f).asInstanceOf[That]
@@ -253,6 +266,7 @@ trait TraversableViewLike[+A,
*/
protected def newForced[B](xs: => GenSeq[B]): Transformed[B] = new { val forced = xs } with AbstractTransformed[B] with Forced[B]
protected def newAppended[B >: A](that: GenTraversable[B]): Transformed[B] = new { val rest = that } with AbstractTransformed[B] with Appended[B]
+ protected def newPrepended[B >: A](that: GenTraversable[B]): Transformed[B] = new { val fst = that } with AbstractTransformed[B] with Prepended[B]
protected def newMapped[B](f: A => B): Transformed[B] = new { val mapping = f } with AbstractTransformed[B] with Mapped[B]
protected def newFlatMapped[B](f: A => GenTraversableOnce[B]): Transformed[B] = new { val mapping = f } with AbstractTransformed[B] with FlatMapped[B]
protected def newFiltered(p: A => Boolean): Transformed[A] = new { val pred = p } with AbstractTransformed[A] with Filtered
diff --git a/src/library/scala/collection/concurrent/Map.scala b/src/library/scala/collection/concurrent/Map.scala
index cfb567abe9..f27dfd57fc 100644
--- a/src/library/scala/collection/concurrent/Map.scala
+++ b/src/library/scala/collection/concurrent/Map.scala
@@ -86,4 +86,15 @@ trait Map[A, B] extends scala.collection.mutable.Map[A, B] {
* @return `Some(v)` if the given key was previously mapped to some value `v`, or `None` otherwise
*/
def replace(k: A, v: B): Option[B]
+
+ override def getOrElseUpdate(key: A, op: =>B): B = get(key) match {
+ case Some(v) => v
+ case None =>
+ val v = op
+ putIfAbsent(key, v) match {
+ case Some(nv) => nv
+ case None => v
+ }
+ }
+
}
diff --git a/src/library/scala/collection/concurrent/TrieMap.scala b/src/library/scala/collection/concurrent/TrieMap.scala
index bcfea7a463..fe0b5c4f0e 100644
--- a/src/library/scala/collection/concurrent/TrieMap.scala
+++ b/src/library/scala/collection/concurrent/TrieMap.scala
@@ -11,13 +11,11 @@ package collection
package concurrent
import java.util.concurrent.atomic._
-import scala.collection.immutable.{ ListMap => ImmutableListMap }
import scala.collection.parallel.mutable.ParTrieMap
import scala.util.hashing.Hashing
import scala.util.control.ControlThrowable
import generic._
import scala.annotation.tailrec
-import scala.annotation.switch
private[collection] final class INode[K, V](bn: MainNode[K, V], g: Gen) extends INodeBase[K, V](g) {
import INodeBase._
@@ -471,7 +469,7 @@ private[collection] final class CNode[K, V](val bitmap: Int, val array: Array[Ba
val offset =
if (array.length > 0)
//util.Random.nextInt(array.length) /* <-- benchmarks show that this causes observable contention */
- scala.concurrent.forkjoin.ThreadLocalRandom.current.nextInt(0, array.length)
+ java.util.concurrent.ThreadLocalRandom.current.nextInt(0, array.length)
else 0
while (i < array.length) {
val pos = (i + offset) % array.length
@@ -641,7 +639,8 @@ extends scala.collection.concurrent.Map[K, V]
private var rootupdater = rtupd
def hashing = hashingobj
def equality = equalityobj
- @volatile var root = r
+ @deprecated("this field will be made private", "2.12.0")
+ @volatile /*private*/ var root = r
def this(hashf: Hashing[K], ef: Equiv[K]) = this(
INode.newRootNode,
@@ -685,11 +684,14 @@ extends scala.collection.concurrent.Map[K, V]
} while (obj != TrieMapSerializationEnd)
}
- def CAS_ROOT(ov: AnyRef, nv: AnyRef) = rootupdater.compareAndSet(this, ov, nv)
+ @deprecated("this method will be made private", "2.12.0")
+ /*private*/ def CAS_ROOT(ov: AnyRef, nv: AnyRef) = rootupdater.compareAndSet(this, ov, nv)
- def readRoot(abort: Boolean = false): INode[K, V] = RDCSS_READ_ROOT(abort)
+ @deprecated("this method will be made private", "2.12.0")
+ /*private[collection]*/ def readRoot(abort: Boolean = false): INode[K, V] = RDCSS_READ_ROOT(abort)
- def RDCSS_READ_ROOT(abort: Boolean = false): INode[K, V] = {
+ @deprecated("this method will be made private", "2.12.0")
+ /*private[concurrent]*/ def RDCSS_READ_ROOT(abort: Boolean = false): INode[K, V] = {
val r = /*READ*/root
r match {
case in: INode[K, V] => in
@@ -884,7 +886,7 @@ extends scala.collection.concurrent.Map[K, V]
*
* If the specified mapping function throws an exception,
* that exception is rethrown.
- *
+ *
* Note: This method will invoke op at most once.
* However, `op` may be invoked without the result being added to the map if
* a concurrent process is also trying to add a value corresponding to the
@@ -930,6 +932,33 @@ extends scala.collection.concurrent.Map[K, V]
if (nonReadOnly) readOnlySnapshot().iterator
else new TrieMapIterator(0, this)
+ ////////////////////////////////////////////////////////////////////////////
+ //
+ // SI-10177 These methods need overrides as the inherited implementations
+ // call `.iterator` more than once, which doesn't guarantee a coherent
+ // view of the data if there is a concurrent writer
+ // Note that the we don't need overrides for keysIterator or valuesIterator
+ // TrieMapTest validates the behaviour.
+ override def values: Iterable[V] = {
+ if (nonReadOnly) readOnlySnapshot().values
+ else super.values
+ }
+ override def keySet: Set[K] = {
+ if (nonReadOnly) readOnlySnapshot().keySet
+ else super.keySet
+ }
+ override def filterKeys(p: K => Boolean): collection.Map[K, V] = {
+ if (nonReadOnly) readOnlySnapshot().filterKeys(p)
+ else super.filterKeys(p)
+ }
+ override def mapValues[W](f: V => W): collection.Map[K, W] = {
+ if (nonReadOnly) readOnlySnapshot().mapValues(f)
+ else super.mapValues(f)
+ }
+ // END extra overrides
+ ///////////////////////////////////////////////////////////////////
+
+
private def cachedSize() = {
val r = RDCSS_READ_ROOT()
r.cachedSize(this)
@@ -1083,6 +1112,7 @@ private[collection] class TrieMapIterator[K, V](var level: Int, private var ct:
Seq(this)
}
+ @deprecated("this method will be removed", "2.12.0")
def printDebug() {
println("ctrie iterator")
println(stackpos.mkString(","))
@@ -1103,14 +1133,14 @@ private[concurrent] case object TrieMapSerializationEnd
private[concurrent] object Debug {
- import scala.collection._
+ import JavaConverters._
lazy val logbuffer = new java.util.concurrent.ConcurrentLinkedQueue[AnyRef]
def log(s: AnyRef) = logbuffer.add(s)
def flush() {
- for (s <- JavaConversions.asScalaIterator(logbuffer.iterator())) Console.out.println(s.toString)
+ for (s <- logbuffer.iterator().asScala) Console.out.println(s.toString)
logbuffer.clear()
}
diff --git a/src/library/scala/collection/convert/AsJavaConverters.scala b/src/library/scala/collection/convert/AsJavaConverters.scala
new file mode 100644
index 0000000000..c7c1fb9c74
--- /dev/null
+++ b/src/library/scala/collection/convert/AsJavaConverters.scala
@@ -0,0 +1,262 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2006-2016, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | http://www.scala-lang.org/ **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+\* */
+
+package scala
+package collection
+package convert
+
+import java.{ lang => jl, util => ju }, java.util.{ concurrent => juc }
+
+/** Defines converter methods from Scala to Java collections. */
+trait AsJavaConverters {
+ import Wrappers._
+
+ /**
+ * Converts a Scala `Iterator` to a Java `Iterator`.
+ *
+ * The returned Java `Iterator` is backed by the provided Scala `Iterator` and any side-effects of
+ * using it via the Java interface will be visible via the Scala interface and vice versa.
+ *
+ * If the Scala `Iterator` was previously obtained from an implicit or explicit call of
+ * `[[JavaConverters.asScalaIterator]](java.util.Iterator)` then the original Java `Iterator` will
+ * be returned.
+ *
+ * @param i The Scala `Iterator` to be converted.
+ * @return A Java `Iterator` view of the argument.
+ */
+ def asJavaIterator[A](i: Iterator[A]): ju.Iterator[A] = i match {
+ case null => null
+ case JIteratorWrapper(wrapped) => wrapped.asInstanceOf[ju.Iterator[A]]
+ case _ => IteratorWrapper(i)
+ }
+
+ /**
+ * Converts a Scala `Iterator` to a Java `Enumeration`.
+ *
+ * The returned Java `Enumeration` is backed by the provided Scala `Iterator` and any side-effects
+ * of using it via the Java interface will be visible via the Scala interface and vice versa.
+ *
+ * If the Scala `Iterator` was previously obtained from an implicit or explicit call of
+ * `[[JavaConverters.enumerationAsScalaIterator]](java.util.Enumeration)` then the original Java
+ * `Enumeration` will be returned.
+ *
+ * @param i The Scala `Iterator` to be converted.
+ * @return A Java `Enumeration` view of the argument.
+ */
+ def asJavaEnumeration[A](i: Iterator[A]): ju.Enumeration[A] = i match {
+ case null => null
+ case JEnumerationWrapper(wrapped) => wrapped.asInstanceOf[ju.Enumeration[A]]
+ case _ => IteratorWrapper(i)
+ }
+
+ /**
+ * Converts a Scala `Iterable` to a Java `Iterable`.
+ *
+ * The returned Java `Iterable` is backed by the provided Scala `Iterable` and any side-effects of
+ * using it via the Java interface will be visible via the Scala interface and vice versa.
+ *
+ * If the Scala `Iterable` was previously obtained from an implicit or explicit call of
+ * `[[JavaConverters.iterableAsScalaIterable]](java.lang.Iterable)` then the original Java
+ * `Iterable` will be returned.
+ *
+ * @param i The Scala `Iterable` to be converted.
+ * @return A Java `Iterable` view of the argument.
+ */
+ def asJavaIterable[A](i: Iterable[A]): jl.Iterable[A] = i match {
+ case null => null
+ case JIterableWrapper(wrapped) => wrapped.asInstanceOf[jl.Iterable[A]]
+ case _ => IterableWrapper(i)
+ }
+
+ /**
+ * Converts a Scala `Iterable` to an immutable Java `Collection`.
+ *
+ * If the Scala `Iterable` was previously obtained from an implicit or explicit call of
+ * `[[JavaConverters.collectionAsScalaIterable]](java.util.Collection)` then the original Java
+ * `Collection` will be returned.
+ *
+ * @param i The Scala `Iterable` to be converted.
+ * @return A Java `Collection` view of the argument.
+ */
+ def asJavaCollection[A](i: Iterable[A]): ju.Collection[A] = i match {
+ case null => null
+ case JCollectionWrapper(wrapped) => wrapped.asInstanceOf[ju.Collection[A]]
+ case _ => new IterableWrapper(i)
+ }
+
+ /**
+ * Converts a Scala mutable `Buffer` to a Java List.
+ *
+ * The returned Java List is backed by the provided Scala `Buffer` and any side-effects of using
+ * it via the Java interface will be visible via the Scala interface and vice versa.
+ *
+ * If the Scala `Buffer` was previously obtained from an implicit or explicit call of
+ * `[[JavaConverters.asScalaBuffer]](java.util.List)` then the original Java `List` will be
+ * returned.
+ *
+ * @param b The Scala `Buffer` to be converted.
+ * @return A Java `List` view of the argument.
+ */
+ def bufferAsJavaList[A](b: mutable.Buffer[A]): ju.List[A] = b match {
+ case null => null
+ case JListWrapper(wrapped) => wrapped
+ case _ => new MutableBufferWrapper(b)
+ }
+
+ /**
+ * Converts a Scala mutable `Seq` to a Java `List`.
+ *
+ * The returned Java `List` is backed by the provided Scala `Seq` and any side-effects of using it
+ * via the Java interface will be visible via the Scala interface and vice versa.
+ *
+ * If the Scala `Seq` was previously obtained from an implicit or explicit call of
+ * `[[JavaConverters.asScalaBuffer]](java.util.List)` then the original Java `List` will be
+ * returned.
+ *
+ * @param s The Scala `Seq` to be converted.
+ * @return A Java `List` view of the argument.
+ */
+ def mutableSeqAsJavaList[A](s: mutable.Seq[A]): ju.List[A] = s match {
+ case null => null
+ case JListWrapper(wrapped) => wrapped
+ case _ => new MutableSeqWrapper(s)
+ }
+
+ /**
+ * Converts a Scala `Seq` to a Java `List`.
+ *
+ * The returned Java `List` is backed by the provided Scala `Seq` and any side-effects of using it
+ * via the Java interface will be visible via the Scala interface and vice versa.
+ *
+ * If the Scala `Seq` was previously obtained from an implicit or explicit call of
+ * `[[JavaConverters.asScalaBuffer]](java.util.List)` then the original Java `List` will be
+ * returned.
+ *
+ * @param s The Scala `Seq` to be converted.
+ * @return A Java `List` view of the argument.
+ */
+ def seqAsJavaList[A](s: Seq[A]): ju.List[A] = s match {
+ case null => null
+ case JListWrapper(wrapped) => wrapped.asInstanceOf[ju.List[A]]
+ case _ => new SeqWrapper(s)
+ }
+
+ /**
+ * Converts a Scala mutable `Set` to a Java `Set`.
+ *
+ * The returned Java `Set` is backed by the provided Scala `Set` and any side-effects of using it
+ * via the Java interface will be visible via the Scala interface and vice versa.
+ *
+ * If the Scala `Set` was previously obtained from an implicit or explicit call of
+ * `[[JavaConverters.asScalaSet]](java.util.Set)` then the original Java `Set` will be returned.
+ *
+ * @param s The Scala mutable `Set` to be converted.
+ * @return A Java `Set` view of the argument.
+ */
+ def mutableSetAsJavaSet[A](s: mutable.Set[A]): ju.Set[A] = s match {
+ case null => null
+ case JSetWrapper(wrapped) => wrapped
+ case _ => new MutableSetWrapper(s)
+ }
+
+ /**
+ * Converts a Scala `Set` to a Java `Set`.
+ *
+ * The returned Java `Set` is backed by the provided Scala `Set` and any side-effects of using it
+ * via the Java interface will be visible via the Scala interface and vice versa.
+ *
+ * If the Scala `Set` was previously obtained from an implicit or explicit call of
+ * `[[JavaConverters.asScalaSet]](java.util.Set)` then the original Java `Set` will be returned.
+ *
+ * @param s The Scala `Set` to be converted.
+ * @return A Java `Set` view of the argument.
+ */
+ def setAsJavaSet[A](s: Set[A]): ju.Set[A] = s match {
+ case null => null
+ case JSetWrapper(wrapped) => wrapped
+ case _ => new SetWrapper(s)
+ }
+
+ /**
+ * Converts a Scala mutable `Map` to a Java `Map`.
+ *
+ * The returned Java `Map` is backed by the provided Scala `Map` and any side-effects of using it
+ * via the Java interface will be visible via the Scala interface and vice versa.
+ *
+ * If the Scala `Map` was previously obtained from an implicit or explicit call of
+ * `[[JavaConverters.mapAsScalaMap]](java.util.Map)` then the original Java `Map` will be
+ * returned.
+ *
+ * @param m The Scala mutable `Map` to be converted.
+ * @return A Java `Map` view of the argument.
+ */
+ def mutableMapAsJavaMap[A, B](m: mutable.Map[A, B]): ju.Map[A, B] = m match {
+ case null => null
+ case JMapWrapper(wrapped) => wrapped
+ case _ => new MutableMapWrapper(m)
+ }
+
+ /**
+ * Converts a Scala mutable `Map` to a Java `Dictionary`.
+ *
+ * The returned Java `Dictionary` is backed by the provided Scala `Dictionary` and any
+ * side-effects of using it via the Java interface will be visible via the Scala interface and
+ * vice versa.
+ *
+ * If the Scala `Dictionary` was previously obtained from an implicit or explicit call of
+ * `[[JavaConverters.dictionaryAsScalaMap]](java.util.Dictionary)` then the original Java
+ * `Dictionary` will be returned.
+ *
+ * @param m The Scala `Map` to be converted.
+ * @return A Java `Dictionary` view of the argument.
+ */
+ def asJavaDictionary[A, B](m: mutable.Map[A, B]): ju.Dictionary[A, B] = m match {
+ case null => null
+ case JDictionaryWrapper(wrapped) => wrapped
+ case _ => new DictionaryWrapper(m)
+ }
+
+ /**
+ * Converts a Scala `Map` to a Java `Map`.
+ *
+ * The returned Java `Map` is backed by the provided Scala `Map` and any side-effects of using it
+ * via the Java interface will be visible via the Scala interface and vice versa.
+ *
+ * If the Scala `Map` was previously obtained from an implicit or explicit call of
+ * `[[JavaConverters.mapAsScalaMap]](java.util.Map)` then the original Java `Map` will be
+ * returned.
+ *
+ * @param m The Scala `Map` to be converted.
+ * @return A Java `Map` view of the argument.
+ */
+ def mapAsJavaMap[A, B](m: Map[A, B]): ju.Map[A, B] = m match {
+ case null => null
+ case JMapWrapper(wrapped) => wrapped.asInstanceOf[ju.Map[A, B]]
+ case _ => new MapWrapper(m)
+ }
+
+ /**
+ * Converts a Scala mutable `concurrent.Map` to a Java `ConcurrentMap`.
+ *
+ * The returned Java `ConcurrentMap` is backed by the provided Scala `concurrent.Map` and any
+ * side-effects of using it via the Java interface will be visible via the Scala interface and
+ * vice versa.
+ *
+ * If the Scala `concurrent.Map` was previously obtained from an implicit or explicit call of
+ * `[[JavaConverters.mapAsScalaConcurrentMap]](java.util.concurrent.ConcurrentMap)` then the
+ * original Java `ConcurrentMap` will be returned.
+ *
+ * @param m The Scala `concurrent.Map` to be converted.
+ * @return A Java `ConcurrentMap` view of the argument.
+ */
+ def mapAsJavaConcurrentMap[A, B](m: concurrent.Map[A, B]): juc.ConcurrentMap[A, B] = m match {
+ case null => null
+ case JConcurrentMapWrapper(wrapped) => wrapped
+ case _ => new ConcurrentMapWrapper(m)
+ }
+}
diff --git a/src/library/scala/collection/convert/AsScalaConverters.scala b/src/library/scala/collection/convert/AsScalaConverters.scala
new file mode 100644
index 0000000000..f9e38797e1
--- /dev/null
+++ b/src/library/scala/collection/convert/AsScalaConverters.scala
@@ -0,0 +1,207 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2006-2016, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | http://www.scala-lang.org/ **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+\* */
+
+package scala
+package collection
+package convert
+
+import java.{ lang => jl, util => ju }, java.util.{ concurrent => juc }
+
+/** Defines converter methods from Java to Scala collections. */
+trait AsScalaConverters {
+ import Wrappers._
+
+ /**
+ * Converts a Java `Iterator` to a Scala `Iterator`.
+ *
+ * The returned Scala `Iterator` is backed by the provided Java `Iterator` and any side-effects of
+ * using it via the Scala interface will be visible via the Java interface and vice versa.
+ *
+ * If the Java `Iterator` was previously obtained from an implicit or explicit call of
+ * `[[JavaConverters.asJavaIterator]](scala.collection.Iterator)` then the original Scala
+ * `Iterator` will be returned.
+ *
+ * @param i The Java `Iterator` to be converted.
+ * @return A Scala `Iterator` view of the argument.
+ */
+ def asScalaIterator[A](i: ju.Iterator[A]): Iterator[A] = i match {
+ case null => null
+ case IteratorWrapper(wrapped) => wrapped
+ case _ => JIteratorWrapper(i)
+ }
+
+ /**
+ * Converts a Java `Enumeration` to a Scala `Iterator`.
+ *
+ * The returned Scala `Iterator` is backed by the provided Java `Enumeration` and any side-effects
+ * of using it via the Scala interface will be visible via the Java interface and vice versa.
+ *
+ * If the Java `Enumeration` was previously obtained from an implicit or explicit call of
+ * `[[JavaConverters.asJavaEnumeration]](scala.collection.Iterator)` then the original Scala
+ * `Iterator` will be returned.
+ *
+ * @param i The Java `Enumeration` to be converted.
+ * @return A Scala `Iterator` view of the argument.
+ */
+ def enumerationAsScalaIterator[A](i: ju.Enumeration[A]): Iterator[A] = i match {
+ case null => null
+ case IteratorWrapper(wrapped) => wrapped
+ case _ => JEnumerationWrapper(i)
+ }
+
+ /**
+ * Converts a Java `Iterable` to a Scala `Iterable`.
+ *
+ * The returned Scala `Iterable` is backed by the provided Java `Iterable` and any side-effects of
+ * using it via the Scala interface will be visible via the Java interface and vice versa.
+ *
+ * If the Java `Iterable` was previously obtained from an implicit or explicit call of
+ * `[[JavaConverters.asJavaIterable]](scala.collection.Iterable) then the original Scala
+ * `Iterable` will be returned.
+ *
+ * @param i The Java `Iterable` to be converted.
+ * @return A Scala `Iterable` view of the argument.
+ */
+ def iterableAsScalaIterable[A](i: jl.Iterable[A]): Iterable[A] = i match {
+ case null => null
+ case IterableWrapper(wrapped) => wrapped
+ case _ => JIterableWrapper(i)
+ }
+
+ /**
+ * Converts a Java `Collection` to an Scala `Iterable`.
+ *
+ * If the Java `Collection` was previously obtained from an implicit or explicit call of
+ * `[[JavaConverters.asJavaCollection]](scala.collection.Iterable)` then the original Scala
+ * `Iterable` will be returned.
+ *
+ * @param i The Java `Collection` to be converted.
+ * @return A Scala `Iterable` view of the argument.
+ */
+ def collectionAsScalaIterable[A](i: ju.Collection[A]): Iterable[A] = i match {
+ case null => null
+ case IterableWrapper(wrapped) => wrapped
+ case _ => JCollectionWrapper(i)
+ }
+
+ /**
+ * Converts a Java `List` to a Scala mutable `Buffer`.
+ *
+ * The returned Scala `Buffer` is backed by the provided Java `List` and any side-effects of using
+ * it via the Scala interface will be visible via the Java interface and vice versa.
+ *
+ * If the Java `List` was previously obtained from an implicit or explicit call of
+ * `[[JavaConverters.bufferAsJavaList]](scala.collection.mutable.Buffer)` then the original Scala
+ * `Buffer` will be returned.
+ *
+ * @param l The Java `List` to be converted.
+ * @return A Scala mutable `Buffer` view of the argument.
+ */
+ def asScalaBuffer[A](l: ju.List[A]): mutable.Buffer[A] = l match {
+ case null => null
+ case MutableBufferWrapper(wrapped) => wrapped
+ case _ => new JListWrapper(l)
+ }
+
+ /**
+ * Converts a Java `Set` to a Scala mutable `Set`.
+ *
+ * The returned Scala `Set` is backed by the provided Java `Set` and any side-effects of using it
+ * via the Scala interface will be visible via the Java interface and vice versa.
+ *
+ * If the Java `Set` was previously obtained from an implicit or explicit call of
+ * `[[JavaConverters.mutableSetAsJavaSet]](scala.collection.mutable.Set)` then the original Scala
+ * `Set` will be returned.
+ *
+ * @param s The Java `Set` to be converted.
+ * @return A Scala mutable `Set` view of the argument.
+ */
+ def asScalaSet[A](s: ju.Set[A]): mutable.Set[A] = s match {
+ case null => null
+ case MutableSetWrapper(wrapped) => wrapped
+ case _ => new JSetWrapper(s)
+ }
+
+ /**
+ * Converts a Java `Map` to a Scala mutable `Map`.
+ *
+ * The returned Scala `Map` is backed by the provided Java `Map` and any side-effects of using it
+ * via the Scala interface will be visible via the Java interface and vice versa.
+ *
+ * If the Java `Map` was previously obtained from an implicit or explicit call of
+ * `[[JavaConverters.mutableMapAsJavaMap]](scala.collection.mutable.Map)` then the original Scala
+ * `Map` will be returned.
+ *
+ * If the wrapped map is synchronized (e.g. from `java.util.Collections.synchronizedMap`), it is
+ * your responsibility to wrap all non-atomic operations with `underlying.synchronized`.
+ * This includes `get`, as `java.util.Map`'s API does not allow for an atomic `get` when `null`
+ * values may be present.
+ *
+ * @param m The Java `Map` to be converted.
+ * @return A Scala mutable `Map` view of the argument.
+ */
+ def mapAsScalaMap[A, B](m: ju.Map[A, B]): mutable.Map[A, B] = m match {
+ case null => null
+ case MutableMapWrapper(wrapped) => wrapped
+ case _ => new JMapWrapper(m)
+ }
+
+ /**
+ * Converts a Java `ConcurrentMap` to a Scala mutable `ConcurrentMap`.
+ *
+ * The returned Scala `ConcurrentMap` is backed by the provided Java `ConcurrentMap` and any
+ * side-effects of using it via the Scala interface will be visible via the Java interface and
+ * vice versa.
+ *
+ * If the Java `ConcurrentMap` was previously obtained from an implicit or explicit call of
+ * `[[JavaConverters.mapAsJavaConcurrentMap]](scala.collection.mutable.ConcurrentMap)`
+ * then the original Scala `ConcurrentMap` will be returned.
+ *
+ * @param m The Java `ConcurrentMap` to be converted.
+ * @return A Scala mutable `ConcurrentMap` view of the argument.
+ */
+ def mapAsScalaConcurrentMap[A, B](m: juc.ConcurrentMap[A, B]): concurrent.Map[A, B] = m match {
+ case null => null
+ case cmw: ConcurrentMapWrapper[_, _] => cmw.underlying
+ case _ => new JConcurrentMapWrapper(m)
+ }
+
+ /**
+ * Converts a Java `Dictionary` to a Scala mutable `Map`.
+ *
+ * The returned Scala `Map` is backed by the provided Java `Dictionary` and any side-effects of
+ * using it via the Scala interface will be visible via the Java interface and vice versa.
+ *
+ * If the Java `Dictionary` was previously obtained from an implicit or explicit call of
+ * `[[JavaConverters.asJavaDictionary]](scala.collection.mutable.Map)` then the original
+ * Scala `Map` will be returned.
+ *
+ * @param p The Java `Dictionary` to be converted.
+ * @return A Scala mutable `Map` view of the argument.
+ */
+ def dictionaryAsScalaMap[A, B](p: ju.Dictionary[A, B]): mutable.Map[A, B] = p match {
+ case null => null
+ case DictionaryWrapper(wrapped) => wrapped
+ case _ => new JDictionaryWrapper(p)
+ }
+
+ /**
+ * Converts a Java `Properties` to a Scala mutable `Map[String, String]`.
+ *
+ * The returned Scala `Map[String, String]` is backed by the provided Java `Properties` and any
+ * side-effects of using it via the Scala interface will be visible via the Java interface and
+ * vice versa.
+ *
+ * @param p The Java `Properties` to be converted.
+ * @return A Scala mutable `Map[String, String]` view of the argument.
+ */
+ def propertiesAsScalaMap(p: ju.Properties): mutable.Map[String, String] = p match {
+ case null => null
+ case _ => new JPropertiesWrapper(p)
+ }
+}
diff --git a/src/library/scala/collection/convert/DecorateAsJava.scala b/src/library/scala/collection/convert/DecorateAsJava.scala
index e6aa5da067..83fffa5940 100644
--- a/src/library/scala/collection/convert/DecorateAsJava.scala
+++ b/src/library/scala/collection/convert/DecorateAsJava.scala
@@ -1,6 +1,6 @@
/* __ *\
** ________ ___ / / ___ Scala API **
-** / __/ __// _ | / / / _ | (c) 2006-2013, LAMP/EPFL **
+** / __/ __// _ | / / / _ | (c) 2006-2016, LAMP/EPFL **
** __\ \/ /__/ __ |/ /__/ __ | http://www.scala-lang.org/ **
** /____/\___/_/ |_/____/_/ | | **
** |/ **
@@ -12,289 +12,97 @@ package convert
import java.{ lang => jl, util => ju }, java.util.{ concurrent => juc }
import Decorators._
-import WrapAsJava._
import scala.language.implicitConversions
-
-/** A collection of decorators that allow converting between
- * Scala and Java collections using `asScala` and `asJava` methods.
- *
- * The following conversions are supported via `asJava`, `asScala`
- *
- * - `scala.collection.Iterable` <=> `java.lang.Iterable`
- * - `scala.collection.Iterator` <=> `java.util.Iterator`
- * - `scala.collection.mutable.Buffer` <=> `java.util.List`
- * - `scala.collection.mutable.Set` <=> `java.util.Set`
- * - `scala.collection.mutable.Map` <=> `java.util.Map`
- * - `scala.collection.mutable.concurrent.Map` <=> `java.util.concurrent.ConcurrentMap`
- *
- * In all cases, converting from a source type to a target type and back
- * again will return the original source object, e.g.
- * {{{
- * import scala.collection.JavaConverters._
- *
- * val sl = new scala.collection.mutable.ListBuffer[Int]
- * val jl : java.util.List[Int] = sl.asJava
- * val sl2 : scala.collection.mutable.Buffer[Int] = jl.asScala
- * assert(sl eq sl2)
- * }}}
- * The following conversions are also supported, but the
- * direction from Scala to Java is done by the more specifically named methods:
- * `asJavaCollection`, `asJavaEnumeration`, `asJavaDictionary`.
- *
- * - `scala.collection.Iterable` <=> `java.util.Collection`
- * - `scala.collection.Iterator` <=> `java.util.Enumeration`
- * - `scala.collection.mutable.Map` <=> `java.util.Dictionary`
- *
- * In addition, the following one way conversions are provided via `asJava`:
- *
- * - `scala.collection.Seq` => `java.util.List`
- * - `scala.collection.mutable.Seq` => `java.util.List`
- * - `scala.collection.Set` => `java.util.Set`
- * - `scala.collection.Map` => `java.util.Map`
- *
- * The following one way conversion is provided via `asScala`:
- *
- * - `java.util.Properties` => `scala.collection.mutable.Map`
- *
- * @since 2.8.1
- */
-trait DecorateAsJava {
+/** Defines `asJava` extension methods for [[JavaConverters]]. */
+trait DecorateAsJava extends AsJavaConverters {
/**
- * Adds an `asJava` method that implicitly converts a Scala `Iterator` to a
- * Java `Iterator`. The returned Java `Iterator` is backed by the provided Scala
- * `Iterator` and any side-effects of using it via the Java interface will
- * be visible via the Scala interface and vice versa.
- *
- * If the Scala `Iterator` was previously obtained from an implicit or explicit
- * call of `asIterator(java.util.Iterator)` then the original Java `Iterator`
- * will be returned by the `asJava` method.
- *
- * @param i The `Iterator` to be converted.
- * @return An object with an `asJava` method that returns a Java `Iterator` view of the argument.
+ * Adds an `asJava` method that implicitly converts a Scala `Iterator` to a Java `Iterator`.
+ * @see [[asJavaIterator]]
*/
implicit def asJavaIteratorConverter[A](i : Iterator[A]): AsJava[ju.Iterator[A]] =
new AsJava(asJavaIterator(i))
/**
- * Adds an `asJavaEnumeration` method that implicitly converts a Scala
- * `Iterator` to a Java `Enumeration`. The returned Java `Enumeration` is
- * backed by the provided Scala `Iterator` and any side-effects of using
- * it via the Java interface will be visible via the Scala interface and
- * vice versa.
- *
- * If the Scala `Iterator` was previously obtained from an implicit or
- * explicit call of `asIterator(java.util.Enumeration)` then the
- * original Java `Enumeration` will be returned.
- *
- * @param i The `Iterator` to be converted.
- * @return An object with an `asJavaEnumeration` method that returns a Java
- * `Enumeration` view of the argument.
+ * Adds an `asJavaEnumeration` method that implicitly converts a Scala `Iterator` to a Java `Enumeration`.
+ * @see [[asJavaEnumeration]]
*/
implicit def asJavaEnumerationConverter[A](i : Iterator[A]): AsJavaEnumeration[A] =
new AsJavaEnumeration(i)
/**
- * Adds an `asJava` method that implicitly converts a Scala `Iterable` to
- * a Java `Iterable`.
- *
- * The returned Java `Iterable` is backed by the provided Scala `Iterable`
- * and any side-effects of using it via the Java interface will be visible
- * via the Scala interface and vice versa.
- *
- * If the Scala `Iterable` was previously obtained from an implicit or
- * explicit call of `asIterable(java.lang.Iterable)` then the original
- * Java `Iterable` will be returned.
- *
- * @param i The `Iterable` to be converted.
- * @return An object with an `asJavaCollection` method that returns a Java
- * `Iterable` view of the argument.
+ * Adds an `asJava` method that implicitly converts a Scala `Iterable` to a Java `Iterable`.
+ * @see [[asJavaIterable]]
*/
implicit def asJavaIterableConverter[A](i : Iterable[A]): AsJava[jl.Iterable[A]] =
new AsJava(asJavaIterable(i))
/**
- * Adds an `asJavaCollection` method that implicitly converts a Scala
- * `Iterable` to an immutable Java `Collection`.
- *
- * If the Scala `Iterable` was previously obtained from an implicit or
- * explicit call of `asSizedIterable(java.util.Collection)` then the
- * original Java `Collection` will be returned.
- *
- * @param i The `SizedIterable` to be converted.
- * @return An object with an `asJava` method that returns a Java
- * `Collection` view of the argument.
+ * Adds an `asJavaCollection` method that implicitly converts a Scala `Iterable` to an immutable Java `Collection`.
+ * @see [[asJavaCollection]]
*/
implicit def asJavaCollectionConverter[A](i : Iterable[A]): AsJavaCollection[A] =
new AsJavaCollection(i)
/**
- * Adds an `asJava` method that implicitly converts a Scala mutable `Buffer`
- * to a Java `List`.
- *
- * The returned Java `List` is backed by the provided Scala `Buffer` and any
- * side-effects of using it via the Java interface will be visible via the
- * Scala interface and vice versa.
- *
- * If the Scala `Buffer` was previously obtained from an implicit or explicit
- * call of `asBuffer(java.util.List)` then the original Java `List` will be
- * returned.
- *
- * @param b The `Buffer` to be converted.
- * @return An object with an `asJava` method that returns a Java `List` view
- * of the argument.
+ * Adds an `asJava` method that implicitly converts a Scala mutable `Buffer` to a Java `List`.
+ * @see [[bufferAsJavaList]]
*/
implicit def bufferAsJavaListConverter[A](b : mutable.Buffer[A]): AsJava[ju.List[A]] =
new AsJava(bufferAsJavaList(b))
/**
- * Adds an `asJava` method that implicitly converts a Scala mutable `Seq`
- * to a Java `List`.
- *
- * The returned Java `List` is backed by the provided Scala `Seq` and any
- * side-effects of using it via the Java interface will be visible via the
- * Scala interface and vice versa.
- *
- * If the Scala `Seq` was previously obtained from an implicit or explicit
- * call of `asSeq(java.util.List)` then the original Java `List` will be
- * returned.
- *
- * @param b The `Seq` to be converted.
- * @return An object with an `asJava` method that returns a Java `List`
- * view of the argument.
+ * Adds an `asJava` method that implicitly converts a Scala mutable `Seq` to a Java `List`.
+ * @see [[mutableSeqAsJavaList]]
*/
implicit def mutableSeqAsJavaListConverter[A](b : mutable.Seq[A]): AsJava[ju.List[A]] =
new AsJava(mutableSeqAsJavaList(b))
/**
- * Adds an `asJava` method that implicitly converts a Scala `Seq` to a
- * Java `List`.
- *
- * The returned Java `List` is backed by the provided Scala `Seq` and any
- * side-effects of using it via the Java interface will be visible via the
- * Scala interface and vice versa.
- *
- * If the Scala `Seq` was previously obtained from an implicit or explicit
- * call of `asSeq(java.util.List)` then the original Java `List` will be
- * returned.
- *
- * @param b The `Seq` to be converted.
- * @return An object with an `asJava` method that returns a Java `List`
- * view of the argument.
+ * Adds an `asJava` method that implicitly converts a Scala `Seq` to a Java `List`.
+ * @see [[seqAsJavaList]]
*/
implicit def seqAsJavaListConverter[A](b : Seq[A]): AsJava[ju.List[A]] =
new AsJava(seqAsJavaList(b))
/**
- * Adds an `asJava` method that implicitly converts a Scala mutable `Set`>
- * to a Java `Set`.
- *
- * The returned Java `Set` is backed by the provided Scala `Set` and any
- * side-effects of using it via the Java interface will be visible via
- * the Scala interface and vice versa.
- *
- * If the Scala `Set` was previously obtained from an implicit or explicit
- * call of `asSet(java.util.Set)` then the original Java `Set` will be
- * returned.
- *
- * @param s The `Set` to be converted.
- * @return An object with an `asJava` method that returns a Java `Set` view
- * of the argument.
+ * Adds an `asJava` method that implicitly converts a Scala mutable `Set` to a Java `Set`.
+ * @see [[mutableSetAsJavaSet]]
*/
implicit def mutableSetAsJavaSetConverter[A](s : mutable.Set[A]): AsJava[ju.Set[A]] =
new AsJava(mutableSetAsJavaSet(s))
/**
- * Adds an `asJava` method that implicitly converts a Scala `Set` to a
- * Java `Set`.
- *
- * The returned Java `Set` is backed by the provided Scala `Set` and any
- * side-effects of using it via the Java interface will be visible via
- * the Scala interface and vice versa.
- *
- * If the Scala `Set` was previously obtained from an implicit or explicit
- * call of `asSet(java.util.Set)` then the original Java `Set` will be
- * returned.
- *
- * @param s The `Set` to be converted.
- * @return An object with an `asJava` method that returns a Java `Set` view
- * of the argument.
+ * Adds an `asJava` method that implicitly converts a Scala `Set` to a Java `Set`.
+ * @see [[setAsJavaSet]]
*/
implicit def setAsJavaSetConverter[A](s : Set[A]): AsJava[ju.Set[A]] =
new AsJava(setAsJavaSet(s))
/**
- * Adds an `asJava` method that implicitly converts a Scala mutable `Map`
- * to a Java `Map`.
- *
- * The returned Java `Map` is backed by the provided Scala `Map` and any
- * side-effects of using it via the Java interface will be visible via the
- * Scala interface and vice versa.
- *
- * If the Scala `Map` was previously obtained from an implicit or explicit
- * call of `asMap(java.util.Map)` then the original Java `Map` will be
- * returned.
- *
- * @param m The `Map` to be converted.
- * @return An object with an `asJava` method that returns a Java `Map` view
- * of the argument.
+ * Adds an `asJava` method that implicitly converts a Scala mutable `Map` to a Java `Map`.
+ * @see [[mutableMapAsJavaMap]]
*/
implicit def mutableMapAsJavaMapConverter[A, B](m : mutable.Map[A, B]): AsJava[ju.Map[A, B]] =
new AsJava(mutableMapAsJavaMap(m))
/**
- * Adds an `asJavaDictionary` method that implicitly converts a Scala
- * mutable `Map` to a Java `Dictionary`.
- *
- * The returned Java `Dictionary` is backed by the provided Scala
- * `Dictionary` and any side-effects of using it via the Java interface
- * will be visible via the Scala interface and vice versa.
- *
- * If the Scala `Dictionary` was previously obtained from an implicit or
- * explicit call of `asMap(java.util.Dictionary)` then the original
- * Java `Dictionary` will be returned.
- *
- * @param m The `Map` to be converted.
- * @return An object with an `asJavaDictionary` method that returns a
- * Java `Dictionary` view of the argument.
+ * Adds an `asJavaDictionary` method that implicitly converts a Scala mutable `Map` to a Java `Dictionary`.
+ * @see [[asJavaDictionary]]
*/
implicit def asJavaDictionaryConverter[A, B](m : mutable.Map[A, B]): AsJavaDictionary[A, B] =
new AsJavaDictionary(m)
/**
- * Adds an `asJava` method that implicitly converts a Scala `Map` to
- * a Java `Map`.
- *
- * The returned Java `Map` is backed by the provided Scala `Map` and any
- * side-effects of using it via the Java interface will be visible via
- * the Scala interface and vice versa.
- *
- * If the Scala `Map` was previously obtained from an implicit or explicit
- * call of `asMap(java.util.Map)` then the original Java `Map` will be
- * returned.
- *
- * @param m The `Map` to be converted.
- * @return An object with an `asJava` method that returns a Java `Map` view
- * of the argument.
+ * Adds an `asJava` method that implicitly converts a Scala `Map` to a Java `Map`.
+ * @see [[mapAsJavaMap]]
*/
implicit def mapAsJavaMapConverter[A, B](m : Map[A, B]): AsJava[ju.Map[A, B]] =
new AsJava(mapAsJavaMap(m))
/**
- * Adds an `asJava` method that implicitly converts a Scala mutable
- * `concurrent.Map` to a Java `ConcurrentMap`.
- *
- * The returned Java `ConcurrentMap` is backed by the provided Scala
- * `concurrent.Map` and any side-effects of using it via the Java interface
- * will be visible via the Scala interface and vice versa.
- *
- * If the Scala `concurrent.Map` was previously obtained from an implicit or
- * explicit call of `asConcurrentMap(java.util.concurrent.ConcurrentMap)`
- * then the original Java `ConcurrentMap` will be returned.
- *
- * @param m The Scala `concurrent.Map` to be converted.
- * @return An object with an `asJava` method that returns a Java
- * `ConcurrentMap` view of the argument.
+ * Adds an `asJava` method that implicitly converts a Scala mutable `concurrent.Map` to a Java `ConcurrentMap`.
+ * @see [[mapAsJavaConcurrentMap]].
*/
implicit def mapAsJavaConcurrentMapConverter[A, B](m: concurrent.Map[A, B]): AsJava[juc.ConcurrentMap[A, B]] =
new AsJava(mapAsJavaConcurrentMap(m))
diff --git a/src/library/scala/collection/convert/DecorateAsScala.scala b/src/library/scala/collection/convert/DecorateAsScala.scala
index 5448f5f91c..f680aa5267 100644
--- a/src/library/scala/collection/convert/DecorateAsScala.scala
+++ b/src/library/scala/collection/convert/DecorateAsScala.scala
@@ -1,6 +1,6 @@
/* __ *\
** ________ ___ / / ___ Scala API **
-** / __/ __// _ | / / / _ | (c) 2006-2013, LAMP/EPFL **
+** / __/ __// _ | / / / _ | (c) 2006-2016, LAMP/EPFL **
** __\ \/ /__/ __ |/ /__/ __ | http://www.scala-lang.org/ **
** /____/\___/_/ |_/____/_/ | | **
** |/ **
@@ -12,185 +12,76 @@ package convert
import java.{ lang => jl, util => ju }, java.util.{ concurrent => juc }
import Decorators._
-import WrapAsScala._
import scala.language.implicitConversions
-trait DecorateAsScala {
+/** Defines `asScala` extension methods for [[JavaConverters]]. */
+trait DecorateAsScala extends AsScalaConverters {
/**
- * Adds an `asScala` method that implicitly converts a Java `Iterator` to
- * a Scala `Iterator`.
- *
- * The returned Scala `Iterator` is backed by the provided Java `Iterator`
- * and any side-effects of using it via the Scala interface will be visible
- * via the Java interface and vice versa.
- *
- * If the Java `Iterator` was previously obtained from an implicit or
- * explicit call of `asIterator(scala.collection.Iterator)` then the
- * original Scala `Iterator` will be returned.
- *
- * @param i The `Iterator` to be converted.
- * @return An object with an `asScala` method that returns a Scala
- * `Iterator` view of the argument.
+ * Adds an `asScala` method that implicitly converts a Java `Iterator` to a Scala `Iterator`.
+ * @see [[asScalaIterator]]
*/
implicit def asScalaIteratorConverter[A](i : ju.Iterator[A]): AsScala[Iterator[A]] =
new AsScala(asScalaIterator(i))
/**
- * Adds an `asScala` method that implicitly converts a Java `Enumeration`
- * to a Scala `Iterator`.
- *
- * The returned Scala `Iterator` is backed by the provided Java
- * `Enumeration` and any side-effects of using it via the Scala interface
- * will be visible via the Java interface and vice versa.
- *
- * If the Java `Enumeration` was previously obtained from an implicit or
- * explicit call of `asEnumeration(scala.collection.Iterator)` then the
- * original Scala `Iterator` will be returned.
- *
- * @param i The `Enumeration` to be converted.
- * @return An object with an `asScala` method that returns a Scala
- * `Iterator` view of the argument.
+ * Adds an `asScala` method that implicitly converts a Java `Enumeration` to a Scala `Iterator`.
+ * @see [[enumerationAsScalaIterator]]
*/
implicit def enumerationAsScalaIteratorConverter[A](i : ju.Enumeration[A]): AsScala[Iterator[A]] =
new AsScala(enumerationAsScalaIterator(i))
/**
- * Adds an `asScala` method that implicitly converts a Java `Iterable` to
- * a Scala `Iterable`.
- *
- * The returned Scala `Iterable` is backed by the provided Java `Iterable`
- * and any side-effects of using it via the Scala interface will be visible
- * via the Java interface and vice versa.
- *
- * If the Java `Iterable` was previously obtained from an implicit or
- * explicit call of `asIterable(scala.collection.Iterable)` then the original
- * Scala `Iterable` will be returned.
- *
- * @param i The `Iterable` to be converted.
- * @return An object with an `asScala` method that returns a Scala `Iterable`
- * view of the argument.
+ * Adds an `asScala` method that implicitly converts a Java `Iterable` to a Scala `Iterable`.
+ * @see [[iterableAsScalaIterable]]
*/
implicit def iterableAsScalaIterableConverter[A](i : jl.Iterable[A]): AsScala[Iterable[A]] =
new AsScala(iterableAsScalaIterable(i))
/**
- * Adds an `asScala` method that implicitly converts a Java `Collection` to
- * an Scala `Iterable`.
- *
- * If the Java `Collection` was previously obtained from an implicit or
- * explicit call of `asCollection(scala.collection.SizedIterable)` then
- * the original Scala `SizedIterable` will be returned.
- *
- * @param i The `Collection` to be converted.
- * @return An object with an `asScala` method that returns a Scala
- * `SizedIterable` view of the argument.
+ * Adds an `asScala` method that implicitly converts a Java `Collection` to an Scala `Iterable`.
+ * @see [[collectionAsScalaIterable]]
*/
implicit def collectionAsScalaIterableConverter[A](i : ju.Collection[A]): AsScala[Iterable[A]] =
new AsScala(collectionAsScalaIterable(i))
/**
- * Adds an `asScala` method that implicitly converts a Java `List` to a
- * Scala mutable `Buffer`.
- *
- * The returned Scala `Buffer` is backed by the provided Java `List` and
- * any side-effects of using it via the Scala interface will be visible via
- * the Java interface and vice versa.
- *
- * If the Java `List` was previously obtained from an implicit or explicit
- * call of `asList(scala.collection.mutable.Buffer)` then the original
- * Scala `Buffer` will be returned.
- *
- * @param l The `List` to be converted.
- * @return An object with an `asScala` method that returns a Scala mutable
- * `Buffer` view of the argument.
+ * Adds an `asScala` method that implicitly converts a Java `List` to a Scala mutable `Buffer`.
+ * @see [[asScalaBuffer]]
*/
implicit def asScalaBufferConverter[A](l : ju.List[A]): AsScala[mutable.Buffer[A]] =
new AsScala(asScalaBuffer(l))
/**
- * Adds an `asScala` method that implicitly converts a Java `Set` to a
- * Scala mutable `Set`.
- *
- * The returned Scala `Set` is backed by the provided Java `Set` and any
- * side-effects of using it via the Scala interface will be visible via
- * the Java interface and vice versa.
- *
- * If the Java `Set` was previously obtained from an implicit or explicit
- * call of `asSet(scala.collection.mutable.Set)` then the original
- * Scala `Set` will be returned.
- *
- * @param s The `Set` to be converted.
- * @return An object with an `asScala` method that returns a Scala mutable
- * `Set` view of the argument.
+ * Adds an `asScala` method that implicitly converts a Java `Set` to a Scala mutable `Set`.
+ * @see [[asScalaSet]]
*/
implicit def asScalaSetConverter[A](s : ju.Set[A]): AsScala[mutable.Set[A]] =
new AsScala(asScalaSet(s))
/**
- * Adds an `asScala` method that implicitly converts a Java `Map` to a Scala
- * mutable `Map`. The returned Scala `Map` is backed by the provided Java
- * `Map` and any side-effects of using it via the Scala interface will
- * be visible via the Java interface and vice versa.
- *
- * If the Java `Map` was previously obtained from an implicit or explicit
- * call of `asMap(scala.collection.mutable.Map)` then the original
- * Scala `Map` will be returned.
- *
- * If the wrapped map is synchronized (e.g. from `java.util.Collections.synchronizedMap`),
- * it is your responsibility to wrap all
- * non-atomic operations with `underlying.synchronized`.
- * This includes `get`, as `java.util.Map`'s API does not allow for an
- * atomic `get` when `null` values may be present.
- *
- * @param m The `Map` to be converted.
- * @return An object with an `asScala` method that returns a Scala mutable
- * `Map` view of the argument.
+ * Adds an `asScala` method that implicitly converts a Java `Map` to a Scala mutable `Map`.
+ * @see [[mapAsScalaMap]]
*/
implicit def mapAsScalaMapConverter[A, B](m : ju.Map[A, B]): AsScala[mutable.Map[A, B]] =
new AsScala(mapAsScalaMap(m))
/**
- * Adds an `asScala` method that implicitly converts a Java `ConcurrentMap`
- * to a Scala mutable `concurrent.Map`. The returned Scala `concurrent.Map` is
- * backed by the provided Java `ConcurrentMap` and any side-effects of using
- * it via the Scala interface will be visible via the Java interface and
- * vice versa.
- *
- * If the Java `ConcurrentMap` was previously obtained from an implicit or
- * explicit call of `mapAsScalaConcurrentMap(scala.collection.mutable.ConcurrentMap)`
- * then the original Scala `concurrent.Map` will be returned.
- *
- * @param m The `ConcurrentMap` to be converted.
- * @return An object with an `asScala` method that returns a Scala mutable
- * `concurrent.Map` view of the argument.
+ * Adds an `asScala` method that implicitly converts a Java `ConcurrentMap` to a Scala mutable `concurrent.Map`.
+ * @see [[mapAsScalaConcurrentMap]]
*/
implicit def mapAsScalaConcurrentMapConverter[A, B](m: juc.ConcurrentMap[A, B]): AsScala[concurrent.Map[A, B]] =
new AsScala(mapAsScalaConcurrentMap(m))
/**
- * Adds an `asScala` method that implicitly converts a Java `Dictionary`
- * to a Scala mutable `Map[String, String]`. The returned Scala
- * `Map[String, String]` is backed by the provided Java `Dictionary` and
- * any side-effects of using it via the Scala interface will be visible via
- * the Java interface and vice versa.
- *
- * @param p The `Dictionary` to be converted.
- * @return An object with an `asScala` method that returns a Scala mutable
- * `Map[String, String]` view of the argument.
+ * Adds an `asScala` method that implicitly converts a Java `Dictionary` to a Scala mutable `Map`.
+ * @see [[dictionaryAsScalaMap]]
*/
implicit def dictionaryAsScalaMapConverter[A, B](p: ju.Dictionary[A, B]): AsScala[mutable.Map[A, B]] =
new AsScala(dictionaryAsScalaMap(p))
/**
- * Adds an `asScala` method that implicitly converts a Java `Properties`
- * to a Scala mutable `Map[String, String]`. The returned Scala
- * `Map[String, String]` is backed by the provided Java `Properties` and
- * any side-effects of using it via the Scala interface will be visible via
- * the Java interface and vice versa.
- *
- * @param p The `Properties` to be converted.
- * @return An object with an `asScala` method that returns a Scala mutable
- * `Map[String, String]` view of the argument.
+ * Adds an `asScala` method that implicitly converts a Java `Properties` to a Scala mutable `Map[String, String]`.
+ * @see [[propertiesAsScalaMap]]
*/
implicit def propertiesAsScalaMapConverter(p: ju.Properties): AsScala[mutable.Map[String, String]] =
new AsScala(propertiesAsScalaMap(p))
diff --git a/src/library/scala/collection/convert/Decorators.scala b/src/library/scala/collection/convert/Decorators.scala
index d232fa04e1..3e45a02254 100644
--- a/src/library/scala/collection/convert/Decorators.scala
+++ b/src/library/scala/collection/convert/Decorators.scala
@@ -12,7 +12,7 @@ package convert
import java.{ util => ju }
-private[collection] trait Decorators {
+private[collection] object Decorators {
/** Generic class containing the `asJava` converter method */
class AsJava[A](op: => A) {
/** Converts a Scala collection to the corresponding Java collection */
@@ -28,20 +28,18 @@ private[collection] trait Decorators {
/** Generic class containing the `asJavaCollection` converter method */
class AsJavaCollection[A](i: Iterable[A]) {
/** Converts a Scala `Iterable` to a Java `Collection` */
- def asJavaCollection: ju.Collection[A] = JavaConversions.asJavaCollection(i)
+ def asJavaCollection: ju.Collection[A] = JavaConverters.asJavaCollection(i)
}
/** Generic class containing the `asJavaEnumeration` converter method */
class AsJavaEnumeration[A](i: Iterator[A]) {
/** Converts a Scala `Iterator` to a Java `Enumeration` */
- def asJavaEnumeration: ju.Enumeration[A] = JavaConversions.asJavaEnumeration(i)
+ def asJavaEnumeration: ju.Enumeration[A] = JavaConverters.asJavaEnumeration(i)
}
/** Generic class containing the `asJavaDictionary` converter method */
class AsJavaDictionary[A, B](m : mutable.Map[A, B]) {
/** Converts a Scala `Map` to a Java `Dictionary` */
- def asJavaDictionary: ju.Dictionary[A, B] = JavaConversions.asJavaDictionary(m)
+ def asJavaDictionary: ju.Dictionary[A, B] = JavaConverters.asJavaDictionary(m)
}
}
-
-private[collection] object Decorators extends Decorators
diff --git a/src/library/scala/collection/convert/ImplicitConversions.scala b/src/library/scala/collection/convert/ImplicitConversions.scala
new file mode 100644
index 0000000000..35e6ce1616
--- /dev/null
+++ b/src/library/scala/collection/convert/ImplicitConversions.scala
@@ -0,0 +1,171 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2006-2016, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | http://www.scala-lang.org/ **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+\* */
+
+package scala
+package collection
+package convert
+
+import java.{ lang => jl, util => ju }, java.util.{ concurrent => juc }
+import scala.language.implicitConversions
+
+import JavaConverters._
+
+/** Defines implicit converter methods from Java to Scala collections. */
+trait ToScalaImplicits {
+ /** Implicitly converts a Java `Iterator` to a Scala `Iterator`.
+ * @see [[AsScalaConverters.asScalaIterator]]
+ */
+ implicit def `iterator asScala`[A](it: ju.Iterator[A]): Iterator[A] = asScalaIterator(it)
+
+ /** Implicitly converts a Java `Enumeration` to a Scala `Iterator`.
+ * @see [[AsScalaConverters.enumerationAsScalaIterator]]
+ */
+ implicit def `enumeration AsScalaIterator`[A](i: ju.Enumeration[A]): Iterator[A] = enumerationAsScalaIterator(i)
+
+ /** Implicitly converts a Java `Iterable` to a Scala `Iterable`.
+ * @see [[AsScalaConverters.iterableAsScalaIterable]]
+ */
+ implicit def `iterable AsScalaIterable`[A](i: jl.Iterable[A]): Iterable[A] = iterableAsScalaIterable(i)
+
+ /** Implicitly converts a Java `Collection` to an Scala `Iterable`.
+ * @see [[AsScalaConverters.collectionAsScalaIterable]]
+ */
+ implicit def `collection AsScalaIterable`[A](i: ju.Collection[A]): Iterable[A] = collectionAsScalaIterable(i)
+
+ /** Implicitly converts a Java `List` to a Scala mutable `Buffer`.
+ * @see [[AsScalaConverters.asScalaBuffer]]
+ */
+ implicit def `list asScalaBuffer`[A](l: ju.List[A]): mutable.Buffer[A] = asScalaBuffer(l)
+
+ /** Implicitly converts a Java `Set` to a Scala mutable `Set`.
+ * @see [[AsScalaConverters.asScalaSet]]
+ */
+ implicit def `set asScala`[A](s: ju.Set[A]): mutable.Set[A] = asScalaSet(s)
+
+ /** Implicitly converts a Java `Map` to a Scala mutable `Map`.
+ * @see [[AsScalaConverters.mapAsScalaMap]]
+ */
+ implicit def `map AsScala`[A, B](m: ju.Map[A, B]): mutable.Map[A, B] = mapAsScalaMap(m)
+
+ /** Implicitly converts a Java `ConcurrentMap` to a Scala mutable `ConcurrentMap`.
+ * @see [[AsScalaConverters.mapAsScalaConcurrentMap]]
+ */
+ implicit def `map AsScalaConcurrentMap`[A, B](m: juc.ConcurrentMap[A, B]): concurrent.Map[A, B] = mapAsScalaConcurrentMap(m)
+
+ /** Implicitly converts a Java `Dictionary` to a Scala mutable `Map`.
+ * @see [[AsScalaConverters.dictionaryAsScalaMap]]
+ */
+ implicit def `dictionary AsScalaMap`[A, B](p: ju.Dictionary[A, B]): mutable.Map[A, B] = dictionaryAsScalaMap(p)
+
+ /** Implicitly converts a Java `Properties` to a Scala `mutable Map[String, String]`.
+ * @see [[AsScalaConverters.propertiesAsScalaMap]]
+ */
+ implicit def `properties AsScalaMap`(p: ju.Properties): mutable.Map[String, String] = propertiesAsScalaMap(p)
+}
+
+/** Defines implicit conversions from Scala to Java collections. */
+trait ToJavaImplicits {
+ /** Implicitly converts a Scala `Iterator` to a Java `Iterator`.
+ * @see [[AsJavaConverters.asJavaIterator]]
+ */
+ implicit def `iterator asJava`[A](it: Iterator[A]): ju.Iterator[A] = asJavaIterator(it)
+
+ /** Implicitly converts a Scala `Iterator` to a Java `Enumeration`.
+ * @see [[AsJavaConverters.asJavaEnumeration]]
+ */
+ implicit def `enumeration asJava`[A](it: Iterator[A]): ju.Enumeration[A] = asJavaEnumeration(it)
+
+ /** Implicitly converts a Scala `Iterable` to a Java `Iterable`.
+ * @see [[AsJavaConverters.asJavaIterable]]
+ */
+ implicit def `iterable asJava`[A](i: Iterable[A]): jl.Iterable[A] = asJavaIterable(i)
+
+ /** Implicitly converts a Scala `Iterable` to an immutable Java `Collection`.
+ * @see [[AsJavaConverters.asJavaCollection]]
+ */
+ implicit def `collection asJava`[A](it: Iterable[A]): ju.Collection[A] = asJavaCollection(it)
+
+ /** Implicitly converts a Scala mutable `Buffer` to a Java `List`.
+ * @see [[AsJavaConverters.bufferAsJavaList]]
+ */
+ implicit def `buffer AsJavaList`[A](b: mutable.Buffer[A]): ju.List[A] = bufferAsJavaList(b)
+
+ /** Implicitly converts a Scala mutable `Seq` to a Java `List`.
+ * @see [[AsJavaConverters.mutableSeqAsJavaList]]
+ */
+ implicit def `mutableSeq AsJavaList`[A](seq: mutable.Seq[A]): ju.List[A] = mutableSeqAsJavaList(seq)
+
+ /** Implicitly converts a Scala `Seq` to a Java `List`.
+ * @see [[AsJavaConverters.seqAsJavaList]]
+ */
+ implicit def `seq AsJavaList`[A](seq: Seq[A]): ju.List[A] = seqAsJavaList(seq)
+
+ /** Implicitly converts a Scala mutable `Set` to a Java `Set`.
+ * @see [[AsJavaConverters.mutableSetAsJavaSet]]
+ */
+ implicit def `mutableSet AsJavaSet`[A](s: mutable.Set[A]): ju.Set[A] = mutableSetAsJavaSet(s)
+
+ /** Implicitly converts a Scala `Set` to a Java `Set`.
+ * @see [[AsJavaConverters.setAsJavaSet]]
+ */
+ implicit def `set AsJavaSet`[A](s: Set[A]): ju.Set[A] = setAsJavaSet(s)
+
+ /** Implicitly converts a Scala mutable `Map` to a Java `Map`.
+ * @see [[AsJavaConverters.mutableMapAsJavaMap]]
+ */
+ implicit def `mutableMap AsJavaMap`[A, B](m: mutable.Map[A, B]): ju.Map[A, B] = mutableMapAsJavaMap(m)
+
+ /** Implicitly converts a Scala mutable `Map` to a Java `Dictionary`.
+ * @see [[AsJavaConverters.asJavaDictionary]]
+ */
+ implicit def `dictionary asJava`[A, B](m: mutable.Map[A, B]): ju.Dictionary[A, B] = asJavaDictionary(m)
+
+ /** Implicitly converts a Scala `Map` to a Java `Map`.
+ * @see [[AsJavaConverters.mapAsJavaMap]]
+ */
+ implicit def `map AsJavaMap`[A, B](m: Map[A, B]): ju.Map[A, B] = mapAsJavaMap(m)
+
+ /** Implicitly converts a Scala mutable `concurrent.Map` to a Java `ConcurrentMap`.
+ * @see [[AsJavaConverters.mapAsJavaConcurrentMap]]
+ */
+ implicit def `map AsJavaConcurrentMap`[A, B](m: concurrent.Map[A, B]): juc.ConcurrentMap[A, B] = mapAsJavaConcurrentMap(m)
+}
+
+/**
+ * Convenience for miscellaneous implicit conversions from Scala to Java collections API.
+ *
+ * It is recommended to use explicit conversions provided by [[collection.JavaConverters]] instead.
+ * Implicit conversions may cause unexpected issues, see [[ImplicitConversions]].
+ */
+object ImplicitConversionsToJava extends ToJavaImplicits
+
+/**
+ * Convenience for miscellaneous implicit conversions from Java to Scala collections API.
+ *
+ * It is recommended to use explicit conversions provided by [[collection.JavaConverters]] instead.
+ * Implicit conversions may cause unexpected issues, see [[ImplicitConversions]].
+ */
+object ImplicitConversionsToScala extends ToScalaImplicits
+
+/**
+ * Convenience for miscellaneous implicit conversions between Java and Scala collections API.
+ *
+ * It is recommended to use explicit conversions provided by [[collection.JavaConverters]] instead.
+ * Implicit conversions may cause unexpected issues. Example:
+ *
+ * {{{
+ * import collection.convert.ImplicitConversions._
+ * case class StringBox(s: String)
+ * val m = Map(StringBox("one") -> "uno")
+ * m.get("one")
+ * }}}
+ *
+ * The above example returns `null` instead of producing a type error at compile-time. The map is
+ * implicitly converted to a `java.util.Map` which provides a method `get(x: AnyRef)`.
+ */
+object ImplicitConversions extends ToScalaImplicits with ToJavaImplicits
diff --git a/src/library/scala/collection/convert/WrapAsJava.scala b/src/library/scala/collection/convert/WrapAsJava.scala
index 9916fe9843..e3a064b79d 100644
--- a/src/library/scala/collection/convert/WrapAsJava.scala
+++ b/src/library/scala/collection/convert/WrapAsJava.scala
@@ -13,7 +13,27 @@ package convert
import java.{ lang => jl, util => ju }, java.util.{ concurrent => juc }
import scala.language.implicitConversions
-trait WrapAsJava {
+@deprecated("use JavaConverters or consider ToJavaImplicits", since="2.12.0")
+trait WrapAsJava extends LowPriorityWrapAsJava {
+ // provide higher-priority implicits with names that don't exist in JavaConverters for the case
+ // when importing both JavaConverters._ and JavaConversions._. otherwise implicit conversions
+ // would not apply, see https://github.com/scala/scala/pull/5109#issuecomment-212417789
+ implicit def `deprecated asJavaIterator`[A](it: Iterator[A]): ju.Iterator[A] = asJavaIterator(it)
+ implicit def `deprecated asJavaEnumeration`[A](it: Iterator[A]): ju.Enumeration[A] = asJavaEnumeration(it)
+ implicit def `deprecated asJavaIterable`[A](i: Iterable[A]): jl.Iterable[A] = asJavaIterable(i)
+ implicit def `deprecated asJavaCollection`[A](it: Iterable[A]): ju.Collection[A] = asJavaCollection(it)
+ implicit def `deprecated bufferAsJavaList`[A](b: mutable.Buffer[A]): ju.List[A] = bufferAsJavaList(b)
+ implicit def `deprecated mutableSeqAsJavaList`[A](seq: mutable.Seq[A]): ju.List[A] = mutableSeqAsJavaList(seq)
+ implicit def `deprecated seqAsJavaList`[A](seq: Seq[A]): ju.List[A] = seqAsJavaList(seq)
+ implicit def `deprecated mutableSetAsJavaSet`[A](s: mutable.Set[A]): ju.Set[A] = mutableSetAsJavaSet(s)
+ implicit def `deprecated setAsJavaSet`[A](s: Set[A]): ju.Set[A] = setAsJavaSet(s)
+ implicit def `deprecated mutableMapAsJavaMap`[A, B](m: mutable.Map[A, B]): ju.Map[A, B] = mutableMapAsJavaMap(m)
+ implicit def `deprecated asJavaDictionary`[A, B](m: mutable.Map[A, B]): ju.Dictionary[A, B] = asJavaDictionary(m)
+ implicit def `deprecated mapAsJavaMap`[A, B](m: Map[A, B]): ju.Map[A, B] = mapAsJavaMap(m)
+ implicit def `deprecated mapAsJavaConcurrentMap`[A, B](m: concurrent.Map[A, B]): juc.ConcurrentMap[A, B] = mapAsJavaConcurrentMap(m)
+}
+
+private[convert] trait LowPriorityWrapAsJava {
import Wrappers._
/**
@@ -30,8 +50,9 @@ trait WrapAsJava {
* @return A Java Iterator view of the argument.
*/
implicit def asJavaIterator[A](it: Iterator[A]): ju.Iterator[A] = it match {
- case JIteratorWrapper(wrapped) => wrapped.asInstanceOf[ju.Iterator[A]]
- case _ => IteratorWrapper(it)
+ case null => null
+ case JIteratorWrapper(wrapped) => wrapped.asInstanceOf[ju.Iterator[A]]
+ case _ => IteratorWrapper(it)
}
/**
@@ -48,8 +69,9 @@ trait WrapAsJava {
* @return A Java Enumeration view of the argument.
*/
implicit def asJavaEnumeration[A](it: Iterator[A]): ju.Enumeration[A] = it match {
+ case null => null
case JEnumerationWrapper(wrapped) => wrapped.asInstanceOf[ju.Enumeration[A]]
- case _ => IteratorWrapper(it)
+ case _ => IteratorWrapper(it)
}
/**
@@ -66,8 +88,9 @@ trait WrapAsJava {
* @return A Java Iterable view of the argument.
*/
implicit def asJavaIterable[A](i: Iterable[A]): jl.Iterable[A] = i match {
- case JIterableWrapper(wrapped) => wrapped.asInstanceOf[jl.Iterable[A]]
- case _ => IterableWrapper(i)
+ case null => null
+ case JIterableWrapper(wrapped) => wrapped.asInstanceOf[jl.Iterable[A]]
+ case _ => IterableWrapper(i)
}
/**
@@ -82,8 +105,9 @@ trait WrapAsJava {
* @return A Java Collection view of the argument.
*/
implicit def asJavaCollection[A](it: Iterable[A]): ju.Collection[A] = it match {
- case JCollectionWrapper(wrapped) => wrapped.asInstanceOf[ju.Collection[A]]
- case _ => new IterableWrapper(it)
+ case null => null
+ case JCollectionWrapper(wrapped) => wrapped.asInstanceOf[ju.Collection[A]]
+ case _ => new IterableWrapper(it)
}
/**
@@ -100,8 +124,9 @@ trait WrapAsJava {
* @return A Java List view of the argument.
*/
implicit def bufferAsJavaList[A](b: mutable.Buffer[A]): ju.List[A] = b match {
- case JListWrapper(wrapped) => wrapped
- case _ => new MutableBufferWrapper(b)
+ case null => null
+ case JListWrapper(wrapped) => wrapped
+ case _ => new MutableBufferWrapper(b)
}
/**
@@ -118,8 +143,9 @@ trait WrapAsJava {
* @return A Java List view of the argument.
*/
implicit def mutableSeqAsJavaList[A](seq: mutable.Seq[A]): ju.List[A] = seq match {
- case JListWrapper(wrapped) => wrapped
- case _ => new MutableSeqWrapper(seq)
+ case null => null
+ case JListWrapper(wrapped) => wrapped
+ case _ => new MutableSeqWrapper(seq)
}
/**
@@ -136,8 +162,9 @@ trait WrapAsJava {
* @return A Java List view of the argument.
*/
implicit def seqAsJavaList[A](seq: Seq[A]): ju.List[A] = seq match {
- case JListWrapper(wrapped) => wrapped.asInstanceOf[ju.List[A]]
- case _ => new SeqWrapper(seq)
+ case null => null
+ case JListWrapper(wrapped) => wrapped.asInstanceOf[ju.List[A]]
+ case _ => new SeqWrapper(seq)
}
/**
@@ -154,8 +181,9 @@ trait WrapAsJava {
* @return A Java Set view of the argument.
*/
implicit def mutableSetAsJavaSet[A](s: mutable.Set[A]): ju.Set[A] = s match {
+ case null => null
case JSetWrapper(wrapped) => wrapped
- case _ => new MutableSetWrapper(s)
+ case _ => new MutableSetWrapper(s)
}
/**
@@ -172,8 +200,9 @@ trait WrapAsJava {
* @return A Java Set view of the argument.
*/
implicit def setAsJavaSet[A](s: Set[A]): ju.Set[A] = s match {
+ case null => null
case JSetWrapper(wrapped) => wrapped
- case _ => new SetWrapper(s)
+ case _ => new SetWrapper(s)
}
/**
@@ -190,9 +219,9 @@ trait WrapAsJava {
* @return A Java Map view of the argument.
*/
implicit def mutableMapAsJavaMap[A, B](m: mutable.Map[A, B]): ju.Map[A, B] = m match {
- //case JConcurrentMapWrapper(wrapped) => wrapped
+ case null => null
case JMapWrapper(wrapped) => wrapped
- case _ => new MutableMapWrapper(m)
+ case _ => new MutableMapWrapper(m)
}
/**
@@ -210,9 +239,9 @@ trait WrapAsJava {
* @return A Java `Dictionary` view of the argument.
*/
implicit def asJavaDictionary[A, B](m: mutable.Map[A, B]): ju.Dictionary[A, B] = m match {
- //case JConcurrentMapWrapper(wrapped) => wrapped
- case JDictionaryWrapper(wrapped) => wrapped
- case _ => new DictionaryWrapper(m)
+ case null => null
+ case JDictionaryWrapper(wrapped) => wrapped
+ case _ => new DictionaryWrapper(m)
}
/**
@@ -230,9 +259,9 @@ trait WrapAsJava {
* @return A Java `Map` view of the argument.
*/
implicit def mapAsJavaMap[A, B](m: Map[A, B]): ju.Map[A, B] = m match {
- //case JConcurrentMapWrapper(wrapped) => wrapped
+ case null => null
case JMapWrapper(wrapped) => wrapped.asInstanceOf[ju.Map[A, B]]
- case _ => new MapWrapper(m)
+ case _ => new MapWrapper(m)
}
/**
@@ -251,9 +280,11 @@ trait WrapAsJava {
* @return A Java `ConcurrentMap` view of the argument.
*/
implicit def mapAsJavaConcurrentMap[A, B](m: concurrent.Map[A, B]): juc.ConcurrentMap[A, B] = m match {
+ case null => null
case JConcurrentMapWrapper(wrapped) => wrapped
- case _ => new ConcurrentMapWrapper(m)
+ case _ => new ConcurrentMapWrapper(m)
}
}
-object WrapAsJava extends WrapAsJava { }
+@deprecated("use JavaConverters or consider ImplicitConversionsToJava", since="2.12.0")
+object WrapAsJava extends WrapAsJava
diff --git a/src/library/scala/collection/convert/WrapAsScala.scala b/src/library/scala/collection/convert/WrapAsScala.scala
index ab151a6778..fbaafde798 100644
--- a/src/library/scala/collection/convert/WrapAsScala.scala
+++ b/src/library/scala/collection/convert/WrapAsScala.scala
@@ -13,8 +13,26 @@ package convert
import java.{ lang => jl, util => ju }, java.util.{ concurrent => juc }
import scala.language.implicitConversions
-trait WrapAsScala {
+@deprecated("use JavaConverters or consider ToScalaImplicits", since="2.12.0")
+trait WrapAsScala extends LowPriorityWrapAsScala {
+ // provide higher-priority implicits with names that don't exist in JavaConverters for the case
+ // when importing both JavaConverters._ and JavaConversions._. otherwise implicit conversions
+ // would not apply, see https://github.com/scala/scala/pull/5109#issuecomment-212417789
+ implicit def `deprecated asScalaIterator`[A](it: ju.Iterator[A]): Iterator[A] = asScalaIterator(it)
+ implicit def `deprecated enumerationAsScalaIterator`[A](i: ju.Enumeration[A]): Iterator[A] = enumerationAsScalaIterator(i)
+ implicit def `deprecated iterableAsScalaIterable`[A](i: jl.Iterable[A]): Iterable[A] = iterableAsScalaIterable(i)
+ implicit def `deprecated collectionAsScalaIterable`[A](i: ju.Collection[A]): Iterable[A] = collectionAsScalaIterable(i)
+ implicit def `deprecated asScalaBuffer`[A](l: ju.List[A]): mutable.Buffer[A] = asScalaBuffer(l)
+ implicit def `deprecated asScalaSet`[A](s: ju.Set[A]): mutable.Set[A] = asScalaSet(s)
+ implicit def `deprecated mapAsScalaMap`[A, B](m: ju.Map[A, B]): mutable.Map[A, B] = mapAsScalaMap(m)
+ implicit def `deprecated mapAsScalaConcurrentMap`[A, B](m: juc.ConcurrentMap[A, B]): concurrent.Map[A, B] = mapAsScalaConcurrentMap(m)
+ implicit def `deprecated dictionaryAsScalaMap`[A, B](p: ju.Dictionary[A, B]): mutable.Map[A, B] = dictionaryAsScalaMap(p)
+ implicit def `deprecated propertiesAsScalaMap`(p: ju.Properties): mutable.Map[String, String] = propertiesAsScalaMap(p)
+}
+
+private[convert] trait LowPriorityWrapAsScala {
import Wrappers._
+
/**
* Implicitly converts a Java `Iterator` to a Scala `Iterator`.
*
@@ -30,8 +48,9 @@ trait WrapAsScala {
* @return A Scala `Iterator` view of the argument.
*/
implicit def asScalaIterator[A](it: ju.Iterator[A]): Iterator[A] = it match {
+ case null => null
case IteratorWrapper(wrapped) => wrapped
- case _ => JIteratorWrapper(it)
+ case _ => JIteratorWrapper(it)
}
/**
@@ -48,8 +67,9 @@ trait WrapAsScala {
* @return A Scala Iterator view of the argument.
*/
implicit def enumerationAsScalaIterator[A](i: ju.Enumeration[A]): Iterator[A] = i match {
+ case null => null
case IteratorWrapper(wrapped) => wrapped
- case _ => JEnumerationWrapper(i)
+ case _ => JEnumerationWrapper(i)
}
/**
@@ -67,8 +87,9 @@ trait WrapAsScala {
* @return A Scala Iterable view of the argument.
*/
implicit def iterableAsScalaIterable[A](i: jl.Iterable[A]): Iterable[A] = i match {
+ case null => null
case IterableWrapper(wrapped) => wrapped
- case _ => JIterableWrapper(i)
+ case _ => JIterableWrapper(i)
}
/**
@@ -82,8 +103,9 @@ trait WrapAsScala {
* @return A Scala Iterable view of the argument.
*/
implicit def collectionAsScalaIterable[A](i: ju.Collection[A]): Iterable[A] = i match {
+ case null => null
case IterableWrapper(wrapped) => wrapped
- case _ => JCollectionWrapper(i)
+ case _ => JCollectionWrapper(i)
}
/**
@@ -101,8 +123,9 @@ trait WrapAsScala {
* @return A Scala mutable `Buffer` view of the argument.
*/
implicit def asScalaBuffer[A](l: ju.List[A]): mutable.Buffer[A] = l match {
- case MutableBufferWrapper(wrapped) => wrapped
- case _ =>new JListWrapper(l)
+ case null => null
+ case MutableBufferWrapper(wrapped) => wrapped
+ case _ => new JListWrapper(l)
}
/**
@@ -119,8 +142,9 @@ trait WrapAsScala {
* @return A Scala mutable Set view of the argument.
*/
implicit def asScalaSet[A](s: ju.Set[A]): mutable.Set[A] = s match {
+ case null => null
case MutableSetWrapper(wrapped) => wrapped
- case _ =>new JSetWrapper(s)
+ case _ => new JSetWrapper(s)
}
/**
@@ -133,20 +157,20 @@ trait WrapAsScala {
* If the Java `Map` was previously obtained from an implicit or
* explicit call of `mapAsScalaMap(scala.collection.mutable.Map)` then
* the original Scala Map will be returned.
- *
+ *
* If the wrapped map is synchronized (e.g. from `java.util.Collections.synchronizedMap`),
- * it is your responsibility to wrap all
+ * it is your responsibility to wrap all
* non-atomic operations with `underlying.synchronized`.
* This includes `get`, as `java.util.Map`'s API does not allow for an
* atomic `get` when `null` values may be present.
- *
+ *
* @param m The Map to be converted.
* @return A Scala mutable Map view of the argument.
*/
implicit def mapAsScalaMap[A, B](m: ju.Map[A, B]): mutable.Map[A, B] = m match {
- //case ConcurrentMapWrapper(wrapped) => wrapped
+ case null => null
case MutableMapWrapper(wrapped) => wrapped
- case _ => new JMapWrapper(m)
+ case _ => new JMapWrapper(m)
}
/**
@@ -163,24 +187,26 @@ trait WrapAsScala {
* @return A Scala mutable ConcurrentMap view of the argument.
*/
implicit def mapAsScalaConcurrentMap[A, B](m: juc.ConcurrentMap[A, B]): concurrent.Map[A, B] = m match {
- case cmw: ConcurrentMapWrapper[a, b] => cmw.underlying
- case _ => new JConcurrentMapWrapper(m)
+ case null => null
+ case cmw: ConcurrentMapWrapper[_, _] => cmw.underlying
+ case _ => new JConcurrentMapWrapper(m)
}
/**
* Implicitly converts a Java `Dictionary` to a Scala mutable
- * `Map[String, String]`.
+ * `Map`.
*
- * The returned Scala `Map[String, String]` is backed by the provided Java
+ * The returned Scala `Map` is backed by the provided Java
* `Dictionary` and any side-effects of using it via the Scala interface
* will be visible via the Java interface and vice versa.
*
* @param p The Dictionary to be converted.
- * @return A Scala mutable Map[String, String] view of the argument.
+ * @return A Scala mutable Map view of the argument.
*/
implicit def dictionaryAsScalaMap[A, B](p: ju.Dictionary[A, B]): mutable.Map[A, B] = p match {
+ case null => null
case DictionaryWrapper(wrapped) => wrapped
- case _ => new JDictionaryWrapper(p)
+ case _ => new JDictionaryWrapper(p)
}
/**
@@ -194,8 +220,10 @@ trait WrapAsScala {
* @return A Scala mutable Map[String, String] view of the argument.
*/
implicit def propertiesAsScalaMap(p: ju.Properties): mutable.Map[String, String] = p match {
- case _ => new JPropertiesWrapper(p)
+ case null => null
+ case _ => new JPropertiesWrapper(p)
}
}
-object WrapAsScala extends WrapAsScala { }
+@deprecated("use JavaConverters or consider ImplicitConversionsToScala", since="2.12.0")
+object WrapAsScala extends WrapAsScala
diff --git a/src/library/scala/collection/convert/Wrappers.scala b/src/library/scala/collection/convert/Wrappers.scala
index e829a0215b..9f7e3e8174 100644
--- a/src/library/scala/collection/convert/Wrappers.scala
+++ b/src/library/scala/collection/convert/Wrappers.scala
@@ -14,10 +14,7 @@ import java.{ lang => jl, util => ju }, java.util.{ concurrent => juc }
import WrapAsScala._
import WrapAsJava._
-/** Don't put the implementations in the same scope as the implicits
- * which utilize them, or they will stow away into every scope which
- * extends one of those implementations. See SI-5580.
- */
+/** Adapters for Java/Scala collections API. */
private[collection] trait Wrappers {
trait IterableWrapperTrait[A] extends ju.AbstractCollection[A] {
val underlying: Iterable[A]
@@ -31,7 +28,7 @@ private[collection] trait Wrappers {
def next() = underlying.next()
def hasMoreElements = underlying.hasNext
def nextElement() = underlying.next()
- def remove() = throw new UnsupportedOperationException
+ override def remove() = throw new UnsupportedOperationException
}
class ToIteratorWrapper[A](underlying : Iterator[A]) {
@@ -102,9 +99,9 @@ private[collection] trait Wrappers {
override def clone(): JListWrapper[A] = JListWrapper(new ju.ArrayList[A](underlying))
}
- // Note various overrides to avoid performance gotchas.
- class SetWrapper[A](underlying: Set[A]) extends ju.AbstractSet[A] {
- self =>
+ @SerialVersionUID(1L)
+ class SetWrapper[A](underlying: Set[A]) extends ju.AbstractSet[A] with Serializable { self =>
+ // Note various overrides to avoid performance gotchas.
override def contains(o: Object): Boolean = {
try { underlying.contains(o.asInstanceOf[A]) }
catch { case cce: ClassCastException => false }
@@ -116,7 +113,7 @@ private[collection] trait Wrappers {
var prev: Option[A] = None
def hasNext = ui.hasNext
def next = { val e = ui.next(); prev = Some(e); e }
- def remove = prev match {
+ override def remove() = prev match {
case Some(e) =>
underlying match {
case ms: mutable.Set[a] =>
@@ -165,7 +162,8 @@ private[collection] trait Wrappers {
new JSetWrapper[A](new ju.LinkedHashSet[A](underlying))
}
- class MapWrapper[A, B](underlying: Map[A, B]) extends ju.AbstractMap[A, B] { self =>
+ @SerialVersionUID(1L)
+ class MapWrapper[A, B](underlying: Map[A, B]) extends ju.AbstractMap[A, B] with Serializable { self =>
override def size = underlying.size
override def get(key: AnyRef): B = try {
@@ -202,7 +200,7 @@ private[collection] trait Wrappers {
}
}
- def remove() {
+ override def remove() {
prev match {
case Some(k) =>
underlying match {
@@ -295,24 +293,24 @@ private[collection] trait Wrappers {
class ConcurrentMapWrapper[A, B](override val underlying: concurrent.Map[A, B]) extends MutableMapWrapper[A, B](underlying) with juc.ConcurrentMap[A, B] {
- def putIfAbsent(k: A, v: B) = underlying.putIfAbsent(k, v) match {
+ override def putIfAbsent(k: A, v: B) = underlying.putIfAbsent(k, v) match {
case Some(v) => v
case None => null.asInstanceOf[B]
}
- def remove(k: AnyRef, v: AnyRef) = try {
+ override def remove(k: AnyRef, v: AnyRef) = try {
underlying.remove(k.asInstanceOf[A], v.asInstanceOf[B])
} catch {
case ex: ClassCastException =>
false
}
- def replace(k: A, v: B): B = underlying.replace(k, v) match {
+ override def replace(k: A, v: B): B = underlying.replace(k, v) match {
case Some(v) => v
case None => null.asInstanceOf[B]
}
- def replace(k: A, oldval: B, newval: B) = underlying.replace(k, oldval, newval)
+ override def replace(k: A, oldval: B, newval: B) = underlying.replace(k, oldval, newval)
}
/** Wraps a concurrent Java map as a Scala one. Single-element concurrent
diff --git a/src/library/scala/collection/convert/package.scala b/src/library/scala/collection/convert/package.scala
index 13970f9a3e..810d112cd5 100644
--- a/src/library/scala/collection/convert/package.scala
+++ b/src/library/scala/collection/convert/package.scala
@@ -10,10 +10,17 @@ package scala
package collection
package object convert {
+ @deprecated("use JavaConverters", since="2.12.0")
val decorateAsJava = new DecorateAsJava { }
+ @deprecated("use JavaConverters", since="2.12.0")
val decorateAsScala = new DecorateAsScala { }
- val decorateAll = new DecorateAsJava with DecorateAsScala { }
+ @deprecated("use JavaConverters", since="2.12.0")
+ val decorateAll = JavaConverters
+
+ @deprecated("use JavaConverters or consider ImplicitConversionsToJava", since="2.12.0")
val wrapAsJava = new WrapAsJava { }
+ @deprecated("use JavaConverters or consider ImplicitConversionsToScala", since="2.12.0")
val wrapAsScala = new WrapAsScala { }
+ @deprecated("use JavaConverters or consider ImplicitConversions", since="2.12.0")
val wrapAll = new WrapAsJava with WrapAsScala { }
}
diff --git a/src/library/scala/collection/generic/BitOperations.scala b/src/library/scala/collection/generic/BitOperations.scala
index d430ece2f5..2f460eee1f 100644
--- a/src/library/scala/collection/generic/BitOperations.scala
+++ b/src/library/scala/collection/generic/BitOperations.scala
@@ -26,16 +26,7 @@ private[collection] object BitOperations {
def complement(i: Int) = (-1) ^ i
def bits(num: Int) = 31 to 0 by -1 map (i => (num >>> i & 1) != 0)
def bitString(num: Int, sep: String = "") = bits(num) map (b => if (b) "1" else "0") mkString sep
-
- def highestOneBit(j: Int) = {
- var i = j
- i |= (i >> 1)
- i |= (i >> 2)
- i |= (i >> 4)
- i |= (i >> 8)
- i |= (i >> 16)
- i - (i >>> 1)
- }
+ def highestOneBit(j: Int) = java.lang.Integer.highestOneBit(j)
}
object Int extends Int
@@ -49,17 +40,7 @@ private[collection] object BitOperations {
def complement(i: Long) = (-1L) ^ i
def bits(num: Long) = 63L to 0L by -1L map (i => (num >>> i & 1L) != 0L)
def bitString(num: Long, sep: String = "") = bits(num) map (b => if (b) "1" else "0") mkString sep
-
- def highestOneBit(j: Long) = {
- var i = j
- i |= (i >> 1)
- i |= (i >> 2)
- i |= (i >> 4)
- i |= (i >> 8)
- i |= (i >> 16)
- i |= (i >> 32)
- i - (i >>> 1)
- }
+ def highestOneBit(j: Long) = java.lang.Long.highestOneBit(j)
}
object Long extends Long
}
diff --git a/src/library/scala/collection/generic/GenSetFactory.scala b/src/library/scala/collection/generic/GenSetFactory.scala
index 800f66eb53..65404a4991 100644
--- a/src/library/scala/collection/generic/GenSetFactory.scala
+++ b/src/library/scala/collection/generic/GenSetFactory.scala
@@ -40,7 +40,11 @@ abstract class GenSetFactory[CC[X] <: GenSet[X] with GenSetLike[X, CC[X]]]
/** $setCanBuildFromInfo
*/
def setCanBuildFrom[A] = new CanBuildFrom[CC[_], A, CC[A]] {
- def apply(from: CC[_]) = newBuilder[A]
+ def apply(from: CC[_]) = from match {
+ // When building from an existing Set, try to preserve its type:
+ case from: Set[_] => from.genericBuilder.asInstanceOf[Builder[A, CC[A]]]
+ case _ => newBuilder[A]
+ }
def apply() = newBuilder[A]
}
}
diff --git a/src/library/scala/collection/generic/GenTraversableFactory.scala b/src/library/scala/collection/generic/GenTraversableFactory.scala
index 2092c0c5f5..7c2aa5615c 100644
--- a/src/library/scala/collection/generic/GenTraversableFactory.scala
+++ b/src/library/scala/collection/generic/GenTraversableFactory.scala
@@ -229,7 +229,7 @@ extends GenericCompanion[CC] {
/** Produces a $coll containing repeated applications of a function to a start value.
*
* @param start the start value of the $coll
- * @param len the number of elements contained inthe $coll
+ * @param len the number of elements contained in the $coll
* @param f the function that's repeatedly applied
* @return a $coll with `len` values in the sequence `start, f(start), f(f(start)), ...`
*/
diff --git a/src/library/scala/collection/generic/GenericParTemplate.scala b/src/library/scala/collection/generic/GenericParTemplate.scala
index b9b7043270..44a778a953 100644
--- a/src/library/scala/collection/generic/GenericParTemplate.scala
+++ b/src/library/scala/collection/generic/GenericParTemplate.scala
@@ -13,7 +13,6 @@ package generic
import scala.collection.parallel.Combiner
import scala.collection.parallel.ParIterable
import scala.collection.parallel.ParMap
-import scala.collection.parallel.TaskSupport
import scala.annotation.unchecked.uncheckedVariance
import scala.language.higherKinds
diff --git a/src/library/scala/collection/generic/IterableForwarder.scala b/src/library/scala/collection/generic/IterableForwarder.scala
index 7387dbe667..7f6eb6e131 100644
--- a/src/library/scala/collection/generic/IterableForwarder.scala
+++ b/src/library/scala/collection/generic/IterableForwarder.scala
@@ -26,7 +26,7 @@ import scala.collection._
* @version 2.8
* @since 2.8
*/
-@deprecated("Forwarding is inherently unreliable since it is not automated and methods can be forgotten.", "2.11.0")
+@deprecated("forwarding is inherently unreliable since it is not automated and methods can be forgotten", "2.11.0")
trait IterableForwarder[+A] extends Iterable[A] with TraversableForwarder[A] {
/** The iterable object to which calls are forwarded */
diff --git a/src/library/scala/collection/generic/MapFactory.scala b/src/library/scala/collection/generic/MapFactory.scala
index b9f3d4b010..255d695303 100644
--- a/src/library/scala/collection/generic/MapFactory.scala
+++ b/src/library/scala/collection/generic/MapFactory.scala
@@ -10,8 +10,6 @@ package scala
package collection
package generic
-
-import mutable.{Builder, MapBuilder}
import scala.language.higherKinds
/** A template for companion objects of `Map` and subclasses thereof.
diff --git a/src/library/scala/collection/generic/MutableSortedMapFactory.scala b/src/library/scala/collection/generic/MutableSortedMapFactory.scala
new file mode 100644
index 0000000000..b6fa933ca8
--- /dev/null
+++ b/src/library/scala/collection/generic/MutableSortedMapFactory.scala
@@ -0,0 +1,24 @@
+package scala
+package collection
+package generic
+
+import scala.language.higherKinds
+
+/**
+ * A template for companion objects of `SortedMap` and subclasses thereof.
+ *
+ * @tparam CC the type of the collection.
+ *
+ * @author Rui Gonçalves
+ * @since 2.12
+ * @version 2.12
+ *
+ * @define Coll `mutable.SortedMap`
+ * @define coll mutable sorted map
+ * @define factoryInfo
+ * This object provides a set of operations needed to create sorted maps of type `$Coll`.
+ * @define sortedMapCanBuildFromInfo
+ * The standard `CanBuildFrom` instance for sorted maps
+ */
+abstract class MutableSortedMapFactory[CC[A, B] <: mutable.SortedMap[A, B] with SortedMapLike[A, B, CC[A, B]]]
+ extends SortedMapFactory[CC]
diff --git a/src/library/scala/collection/generic/ParFactory.scala b/src/library/scala/collection/generic/ParFactory.scala
index 4486cea419..901e9fc239 100644
--- a/src/library/scala/collection/generic/ParFactory.scala
+++ b/src/library/scala/collection/generic/ParFactory.scala
@@ -11,7 +11,6 @@ package collection
package generic
import scala.collection.parallel.ParIterable
-import scala.collection.parallel.Combiner
import scala.language.higherKinds
/** A template class for companion objects of `ParIterable` and subclasses
diff --git a/src/library/scala/collection/generic/ParSetFactory.scala b/src/library/scala/collection/generic/ParSetFactory.scala
index 4320635ae6..1341ddcb38 100644
--- a/src/library/scala/collection/generic/ParSetFactory.scala
+++ b/src/library/scala/collection/generic/ParSetFactory.scala
@@ -10,7 +10,6 @@ package scala
package collection
package generic
-import scala.collection.mutable.Builder
import scala.collection.parallel.Combiner
import scala.collection.parallel.ParSet
import scala.collection.parallel.ParSetLike
diff --git a/src/library/scala/collection/generic/SeqForwarder.scala b/src/library/scala/collection/generic/SeqForwarder.scala
index e21e2ea016..cee93d2ddb 100644
--- a/src/library/scala/collection/generic/SeqForwarder.scala
+++ b/src/library/scala/collection/generic/SeqForwarder.scala
@@ -25,7 +25,7 @@ import scala.collection.immutable.Range
* @version 2.8
* @since 2.8
*/
-@deprecated("Forwarding is inherently unreliable since it is not automated and new methods can be forgotten.", "2.11.0")
+@deprecated("forwarding is inherently unreliable since it is not automated and new methods can be forgotten", "2.11.0")
trait SeqForwarder[+A] extends Seq[A] with IterableForwarder[A] {
protected override def underlying: Seq[A]
diff --git a/src/library/scala/collection/generic/SetFactory.scala b/src/library/scala/collection/generic/SetFactory.scala
index fcd8d00c18..5e50844cc9 100644
--- a/src/library/scala/collection/generic/SetFactory.scala
+++ b/src/library/scala/collection/generic/SetFactory.scala
@@ -12,7 +12,6 @@ package scala
package collection
package generic
-import mutable.Builder
import scala.language.higherKinds
abstract class SetFactory[CC[X] <: Set[X] with SetLike[X, CC[X]]]
diff --git a/src/library/scala/collection/generic/TraversableForwarder.scala b/src/library/scala/collection/generic/TraversableForwarder.scala
index 359ea402b6..b94507d6ef 100644
--- a/src/library/scala/collection/generic/TraversableForwarder.scala
+++ b/src/library/scala/collection/generic/TraversableForwarder.scala
@@ -27,7 +27,7 @@ import scala.reflect.ClassTag
* @version 2.8
* @since 2.8
*/
-@deprecated("Forwarding is inherently unreliable since it is not automated and new methods can be forgotten.", "2.11.0")
+@deprecated("forwarding is inherently unreliable since it is not automated and new methods can be forgotten", "2.11.0")
trait TraversableForwarder[+A] extends Traversable[A] {
/** The traversable object to which calls are forwarded. */
protected def underlying: Traversable[A]
diff --git a/src/library/scala/collection/generic/package.scala b/src/library/scala/collection/generic/package.scala
index 1beb4a8599..015c3455db 100644
--- a/src/library/scala/collection/generic/package.scala
+++ b/src/library/scala/collection/generic/package.scala
@@ -1,6 +1,5 @@
package scala
package collection
-import generic.CanBuildFrom
import scala.language.higherKinds
diff --git a/src/library/scala/collection/immutable/BitSet.scala b/src/library/scala/collection/immutable/BitSet.scala
index 70543aa3a6..ecf3326c7f 100644
--- a/src/library/scala/collection/immutable/BitSet.scala
+++ b/src/library/scala/collection/immutable/BitSet.scala
@@ -14,7 +14,7 @@ package immutable
import generic._
import BitSetLike.{LogWL, updateArray}
-import mutable.{ Builder, SetBuilder }
+import mutable.Builder
/** A class for immutable bitsets.
* $bitsetinfo
@@ -68,6 +68,8 @@ object BitSet extends BitSetFactory[BitSet] {
/** The empty bitset */
val empty: BitSet = new BitSet1(0L)
+ private def createSmall(a: Long, b: Long): BitSet = if (b == 0L) new BitSet1(a) else new BitSet2(a, b)
+
/** A builder that takes advantage of mutable BitSets. */
def newBuilder: Builder[Int, BitSet] = new Builder[Int, BitSet] {
private[this] val b = new mutable.BitSet
@@ -84,7 +86,7 @@ object BitSet extends BitSetFactory[BitSet] {
val len = elems.length
if (len == 0) empty
else if (len == 1) new BitSet1(elems(0))
- else if (len == 2) new BitSet2(elems(0), elems(1))
+ else if (len == 2) createSmall(elems(0), elems(1))
else {
val a = new Array[Long](len)
Array.copy(elems, 0, a, 0, len)
@@ -99,17 +101,24 @@ object BitSet extends BitSetFactory[BitSet] {
val len = elems.length
if (len == 0) empty
else if (len == 1) new BitSet1(elems(0))
- else if (len == 2) new BitSet2(elems(0), elems(1))
+ else if (len == 2) createSmall(elems(0), elems(1))
else new BitSetN(elems)
}
+ @SerialVersionUID(2260107458435649300L)
class BitSet1(val elems: Long) extends BitSet {
protected def nwords = 1
protected def word(idx: Int) = if (idx == 0) elems else 0L
protected def updateWord(idx: Int, w: Long): BitSet =
if (idx == 0) new BitSet1(w)
- else if (idx == 1) new BitSet2(elems, w)
+ else if (idx == 1) createSmall(elems, w)
else fromBitMaskNoCopy(updateArray(Array(elems), idx, w))
+ override def head: Int =
+ if (elems == 0L) throw new NoSuchElementException("Empty BitSet")
+ else java.lang.Long.numberOfTrailingZeros(elems)
+ override def tail: BitSet =
+ if (elems == 0L) throw new NoSuchElementException("Empty BitSet")
+ else new BitSet1(elems - java.lang.Long.lowestOneBit(elems))
}
class BitSet2(val elems0: Long, elems1: Long) extends BitSet {
@@ -117,8 +126,20 @@ object BitSet extends BitSetFactory[BitSet] {
protected def word(idx: Int) = if (idx == 0) elems0 else if (idx == 1) elems1 else 0L
protected def updateWord(idx: Int, w: Long): BitSet =
if (idx == 0) new BitSet2(w, elems1)
- else if (idx == 1) new BitSet2(elems0, w)
+ else if (idx == 1) createSmall(elems0, w)
else fromBitMaskNoCopy(updateArray(Array(elems0, elems1), idx, w))
+ override def head: Int =
+ if (elems0 == 0L) {
+ if (elems1 == 0) throw new NoSuchElementException("Empty BitSet")
+ 64 + java.lang.Long.numberOfTrailingZeros(elems1)
+ }
+ else java.lang.Long.numberOfTrailingZeros(elems0)
+ override def tail: BitSet =
+ if (elems0 == 0L) {
+ if (elems1 == 0L) throw new NoSuchElementException("Empty BitSet")
+ createSmall(elems0, elems1 - java.lang.Long.lowestOneBit(elems1))
+ }
+ else new BitSet2(elems0 - java.lang.Long.lowestOneBit(elems0), elems1)
}
/** The implementing class for bit sets with elements >= 128 (exceeding
@@ -131,5 +152,15 @@ object BitSet extends BitSetFactory[BitSet] {
protected def nwords = elems.length
protected def word(idx: Int) = if (idx < nwords) elems(idx) else 0L
protected def updateWord(idx: Int, w: Long): BitSet = fromBitMaskNoCopy(updateArray(elems, idx, w))
+ override def tail: BitSet = {
+ val n = nwords
+ var i = 0
+ while (i < n) {
+ val wi = word(i)
+ if (wi != 0L) return fromBitMaskNoCopy(updateArray(elems, i, wi - java.lang.Long.lowestOneBit(wi)))
+ i += 1
+ }
+ throw new NoSuchElementException("Empty BitSet")
+ }
}
}
diff --git a/src/library/scala/collection/immutable/HashMap.scala b/src/library/scala/collection/immutable/HashMap.scala
index 3e482f1369..627f723cb0 100644
--- a/src/library/scala/collection/immutable/HashMap.scala
+++ b/src/library/scala/collection/immutable/HashMap.scala
@@ -33,8 +33,7 @@ import parallel.immutable.ParHashMap
* @define willNotTerminateInf
*/
@SerialVersionUID(2L)
-@deprecatedInheritance("The implementation details of immutable hash maps make inheriting from them unwise.", "2.11.0")
-class HashMap[A, +B] extends AbstractMap[A, B]
+sealed class HashMap[A, +B] extends AbstractMap[A, B]
with Map[A, B]
with MapLike[A, B, HashMap[A, B]]
with Serializable
@@ -53,6 +52,9 @@ class HashMap[A, +B] extends AbstractMap[A, B]
def get(key: A): Option[B] =
get0(key, computeHash(key), 0)
+ override final def contains(key: A): Boolean =
+ contains0(key, computeHash(key), 0)
+
override def updated [B1 >: B] (key: A, value: B1): HashMap[A, B1] =
updated0(key, computeHash(key), 0, value, null, null)
@@ -65,6 +67,8 @@ class HashMap[A, +B] extends AbstractMap[A, B]
def - (key: A): HashMap[A, B] =
removed0(key, computeHash(key), 0)
+ override def tail: HashMap[A, B] = this - head._1
+
override def filter(p: ((A, B)) => Boolean) = {
val buffer = new Array[HashMap[A, B]](bufferSize(size))
nullToEmpty(filter0(p, false, 0, buffer, 0))
@@ -91,7 +95,7 @@ class HashMap[A, +B] extends AbstractMap[A, B]
import HashMap.{Merger, MergeFunction, liftMerger}
private[collection] def get0(key: A, hash: Int, level: Int): Option[B] = None
-
+ protected def contains0(key: A, hash: Int, level: Int): Boolean = false
private[collection] def updated0[B1 >: B](key: A, hash: Int, level: Int, value: B1, kv: (A, B1), merger: Merger[A, B1]): HashMap[A, B1] =
new HashMap.HashMap1(key, hash, value, kv)
@@ -156,7 +160,10 @@ object HashMap extends ImmutableMapFactory[HashMap] with BitOperations.Int {
implicit def canBuildFrom[A, B]: CanBuildFrom[Coll, (A, B), HashMap[A, B]] = new MapCanBuildFrom[A, B]
def empty[A, B]: HashMap[A, B] = EmptyHashMap.asInstanceOf[HashMap[A, B]]
- private object EmptyHashMap extends HashMap[Any, Nothing] { }
+ private object EmptyHashMap extends HashMap[Any, Nothing] {
+ override def head: (Any, Nothing) = throw new NoSuchElementException("Empty Map")
+ override def tail: HashMap[Any, Nothing] = throw new NoSuchElementException("Empty Map")
+ }
// utility method to create a HashTrieMap from two leaf HashMaps (HashMap1 or HashMapCollision1) with non-colliding hash code)
private def makeHashTrieMap[A, B](hash0:Int, elem0:HashMap[A, B], hash1:Int, elem1:HashMap[A, B], level:Int, size:Int) : HashTrieMap[A, B] = {
@@ -181,6 +188,7 @@ object HashMap extends ImmutableMapFactory[HashMap] with BitOperations.Int {
}
}
+ @deprecatedInheritance("This class will be made final in a future release.", "2.12.2")
class HashMap1[A,+B](private[collection] val key: A, private[collection] val hash: Int, private[collection] val value: (B @uV), private[collection] var kv: (A,B @uV)) extends HashMap[A,B] {
override def size = 1
@@ -191,6 +199,8 @@ object HashMap extends ImmutableMapFactory[HashMap] with BitOperations.Int {
override def get0(key: A, hash: Int, level: Int): Option[B] =
if (hash == this.hash && key == this.key) Some(value) else None
+ override protected def contains0(key: A, hash: Int, level: Int): Boolean =
+ hash == this.hash && key == this.key
private[collection] override def updated0[B1 >: B](key: A, hash: Int, level: Int, value: B1, kv: (A, B1), merger: Merger[A, B1]): HashMap[A, B1] =
if (hash == this.hash && key == this.key ) {
if (merger eq null) {
@@ -235,6 +245,9 @@ object HashMap extends ImmutableMapFactory[HashMap] with BitOperations.Int {
override def get0(key: A, hash: Int, level: Int): Option[B] =
if (hash == this.hash) kvs.get(key) else None
+ override protected def contains0(key: A, hash: Int, level: Int): Boolean =
+ hash == this.hash && kvs.contains(key)
+
private[collection] override def updated0[B1 >: B](key: A, hash: Int, level: Int, value: B1, kv: (A, B1), merger: Merger[A, B1]): HashMap[A, B1] =
if (hash == this.hash) {
if ((merger eq null) || !kvs.contains(key)) new HashMapCollision1(hash, kvs.updated(key, value))
@@ -290,6 +303,7 @@ object HashMap extends ImmutableMapFactory[HashMap] with BitOperations.Int {
}
}
+ @deprecatedInheritance("This class will be made final in a future release.", "2.12.2")
class HashTrieMap[A, +B](
private[collection] val bitmap: Int,
private[collection] val elems: Array[HashMap[A, B @uV]],
@@ -302,21 +316,41 @@ object HashMap extends ImmutableMapFactory[HashMap] with BitOperations.Int {
override def size = size0
override def get0(key: A, hash: Int, level: Int): Option[B] = {
+ // Note: this code is duplicated with `contains0`
+ val index = (hash >>> level) & 0x1f
+ if (bitmap == - 1) {
+ elems(index).get0(key, hash, level + 5)
+ } else {
+ val mask = (1 << index)
+ if ((bitmap & mask) != 0) {
+ val offset = Integer.bitCount(bitmap & (mask - 1))
+ elems(offset).get0(key, hash, level + 5)
+ } else {
+ None
+ }
+ }
+ }
+
+ override protected def contains0(key: A, hash: Int, level: Int): Boolean = {
+ // Note: this code is duplicated from `get0`
val index = (hash >>> level) & 0x1f
- val mask = (1 << index)
if (bitmap == - 1) {
- elems(index & 0x1f).get0(key, hash, level + 5)
- } else if ((bitmap & mask) != 0) {
- val offset = Integer.bitCount(bitmap & (mask-1))
- elems(offset).get0(key, hash, level + 5)
- } else
- None
+ elems(index).contains0(key, hash, level + 5)
+ } else {
+ val mask = (1 << index)
+ if ((bitmap & mask) != 0) {
+ val offset = Integer.bitCount(bitmap & (mask - 1))
+ elems(offset).contains0(key, hash, level + 5)
+ } else {
+ false
+ }
+ }
}
private[collection] override def updated0[B1 >: B](key: A, hash: Int, level: Int, value: B1, kv: (A, B1), merger: Merger[A, B1]): HashMap[A, B1] = {
val index = (hash >>> level) & 0x1f
val mask = (1 << index)
- val offset = Integer.bitCount(bitmap & (mask-1))
+ val offset = Integer.bitCount(bitmap & (mask - 1))
if ((bitmap & mask) != 0) {
val sub = elems(offset)
val subNew = sub.updated0(key, hash, level + 5, value, kv, merger)
@@ -338,7 +372,7 @@ object HashMap extends ImmutableMapFactory[HashMap] with BitOperations.Int {
override def removed0(key: A, hash: Int, level: Int): HashMap[A, B] = {
val index = (hash >>> level) & 0x1f
val mask = (1 << index)
- val offset = Integer.bitCount(bitmap & (mask-1))
+ val offset = Integer.bitCount(bitmap & (mask - 1))
if ((bitmap & mask) != 0) {
val sub = elems(offset)
val subNew = sub.removed0(key, hash, level + 5)
diff --git a/src/library/scala/collection/immutable/HashSet.scala b/src/library/scala/collection/immutable/HashSet.scala
index 050e90b49b..fc937e3a22 100644
--- a/src/library/scala/collection/immutable/HashSet.scala
+++ b/src/library/scala/collection/immutable/HashSet.scala
@@ -31,8 +31,7 @@ import scala.annotation.tailrec
* @define coll immutable hash set
*/
@SerialVersionUID(2L)
-@deprecatedInheritance("The implementation details of immutable hash sets make inheriting from them unwise.", "2.11.0")
-class HashSet[A] extends AbstractSet[A]
+sealed class HashSet[A] extends AbstractSet[A]
with Set[A]
with GenericSetTemplate[A, HashSet]
with SetLike[A, HashSet[A]]
@@ -162,6 +161,8 @@ class HashSet[A] extends AbstractSet[A]
def - (e: A): HashSet[A] =
nullToEmpty(removed0(e, computeHash(e), 0))
+ override def tail: HashSet[A] = this - head
+
override def filter(p: A => Boolean) = {
val buffer = new Array[HashSet[A]](bufferSize(size))
nullToEmpty(filter0(p, false, 0, buffer, 0))
@@ -187,7 +188,7 @@ class HashSet[A] extends AbstractSet[A]
protected def get0(key: A, hash: Int, level: Int): Boolean = false
- def updated0(key: A, hash: Int, level: Int): HashSet[A] =
+ private[collection] def updated0(key: A, hash: Int, level: Int): HashSet[A] =
new HashSet.HashSet1(key, hash)
protected def removed0(key: A, hash: Int, level: Int): HashSet[A] = this
@@ -213,7 +214,10 @@ object HashSet extends ImmutableSetFactory[HashSet] {
/** $setCanBuildFromInfo */
implicit def canBuildFrom[A]: CanBuildFrom[Coll, A, HashSet[A]] = setCanBuildFrom[A]
- private object EmptyHashSet extends HashSet[Any] { }
+ private object EmptyHashSet extends HashSet[Any] {
+ override def head: Any = throw new NoSuchElementException("Empty Set")
+ override def tail: HashSet[Any] = throw new NoSuchElementException("Empty Set")
+ }
private[collection] def emptyInstance: HashSet[Any] = EmptyHashSet
// utility method to create a HashTrieSet from two leaf HashSets (HashSet1 or HashSetCollision1) with non-colliding hash code)
@@ -250,10 +254,10 @@ object HashSet extends ImmutableSetFactory[HashSet] {
class HashSet1[A](private[HashSet] val key: A, private[HashSet] val hash: Int) extends LeafHashSet[A] {
override def size = 1
- override def get0(key: A, hash: Int, level: Int): Boolean =
+ override protected def get0(key: A, hash: Int, level: Int): Boolean =
(hash == this.hash && key == this.key)
- override def subsetOf0(that: HashSet[A], level: Int) = {
+ override protected def subsetOf0(that: HashSet[A], level: Int) = {
// check if that contains this.key
// we use get0 with our key and hash at the correct level instead of calling contains,
// which would not work since that might not be a top-level HashSet
@@ -261,7 +265,7 @@ object HashSet extends ImmutableSetFactory[HashSet] {
that.get0(key, hash, level)
}
- override def updated0(key: A, hash: Int, level: Int): HashSet[A] =
+ override private[collection] def updated0(key: A, hash: Int, level: Int): HashSet[A] =
if (hash == this.hash && key == this.key) this
else {
if (hash != this.hash) {
@@ -306,7 +310,7 @@ object HashSet extends ImmutableSetFactory[HashSet] {
override private[immutable] def diff0(that: HashSet[A], level: Int, buffer: Array[HashSet[A]], offset0: Int): HashSet[A] =
if (that.get0(key, hash, level)) null else this
- override def removed0(key: A, hash: Int, level: Int): HashSet[A] =
+ override protected def removed0(key: A, hash: Int, level: Int): HashSet[A] =
if (hash == this.hash && key == this.key) null else this
override protected def filter0(p: A => Boolean, negate: Boolean, level: Int, buffer: Array[HashSet[A]], offset0: Int): HashSet[A] =
@@ -320,10 +324,10 @@ object HashSet extends ImmutableSetFactory[HashSet] {
override def size = ks.size
- override def get0(key: A, hash: Int, level: Int): Boolean =
+ override protected def get0(key: A, hash: Int, level: Int): Boolean =
if (hash == this.hash) ks.contains(key) else false
- override def subsetOf0(that: HashSet[A], level: Int) = {
+ override protected def subsetOf0(that: HashSet[A], level: Int) = {
// we have to check each element
// we use get0 with our hash at the correct level instead of calling contains,
// which would not work since that might not be a top-level HashSet
@@ -331,11 +335,11 @@ object HashSet extends ImmutableSetFactory[HashSet] {
ks.forall(key => that.get0(key, hash, level))
}
- override def updated0(key: A, hash: Int, level: Int): HashSet[A] =
+ override private[collection] def updated0(key: A, hash: Int, level: Int): HashSet[A] =
if (hash == this.hash) new HashSetCollision1(hash, ks + key)
else makeHashTrieSet(this.hash, this, hash, new HashSet1(key, hash), level)
- override def union0(that: LeafHashSet[A], level: Int): HashSet[A] = that match {
+ override private[immutable] def union0(that: LeafHashSet[A], level: Int): HashSet[A] = that match {
case that if that.hash != this.hash =>
// different hash code, so there is no need to investigate further.
// Just create a branch node containing the two.
@@ -368,7 +372,7 @@ object HashSet extends ImmutableSetFactory[HashSet] {
}
}
- override def union0(that: HashSet[A], level: Int, buffer: Array[HashSet[A]], offset0: Int): HashSet[A] = that match {
+ override private[immutable] def union0(that: HashSet[A], level: Int, buffer: Array[HashSet[A]], offset0: Int): HashSet[A] = that match {
case that: LeafHashSet[A] =>
// switch to the simpler Tree/Leaf implementation
this.union0(that, level)
@@ -425,7 +429,7 @@ object HashSet extends ImmutableSetFactory[HashSet] {
}
}
- override def removed0(key: A, hash: Int, level: Int): HashSet[A] =
+ override protected def removed0(key: A, hash: Int, level: Int): HashSet[A] =
if (hash == this.hash) {
val ks1 = ks - key
ks1.size match {
@@ -522,7 +526,7 @@ object HashSet extends ImmutableSetFactory[HashSet] {
override def size = size0
- override def get0(key: A, hash: Int, level: Int): Boolean = {
+ override protected def get0(key: A, hash: Int, level: Int): Boolean = {
val index = (hash >>> level) & 0x1f
val mask = (1 << index)
if (bitmap == - 1) {
@@ -534,7 +538,7 @@ object HashSet extends ImmutableSetFactory[HashSet] {
false
}
- override def updated0(key: A, hash: Int, level: Int): HashSet[A] = {
+ override private[collection] def updated0(key: A, hash: Int, level: Int): HashSet[A] = {
val index = (hash >>> level) & 0x1f
val mask = (1 << index)
val offset = Integer.bitCount(bitmap & (mask-1))
@@ -836,7 +840,7 @@ object HashSet extends ImmutableSetFactory[HashSet] {
case _ => this
}
- override def removed0(key: A, hash: Int, level: Int): HashSet[A] = {
+ override protected def removed0(key: A, hash: Int, level: Int): HashSet[A] = {
val index = (hash >>> level) & 0x1f
val mask = (1 << index)
val offset = Integer.bitCount(bitmap & (mask-1))
@@ -873,7 +877,7 @@ object HashSet extends ImmutableSetFactory[HashSet] {
}
}
- override def subsetOf0(that: HashSet[A], level: Int): Boolean = if (that eq this) true else that match {
+ override protected def subsetOf0(that: HashSet[A], level: Int): Boolean = if (that eq this) true else that match {
case that: HashTrieSet[A] if this.size0 <= that.size0 =>
// create local mutable copies of members
var abm = this.bitmap
diff --git a/src/library/scala/collection/immutable/List.scala b/src/library/scala/collection/immutable/List.scala
index 8e8bf953f3..550b987cb6 100644
--- a/src/library/scala/collection/immutable/List.scala
+++ b/src/library/scala/collection/immutable/List.scala
@@ -13,7 +13,7 @@ package immutable
import generic._
import mutable.{Builder, ListBuffer}
import scala.annotation.tailrec
-import java.io._
+import java.io.{ObjectOutputStream, ObjectInputStream}
/** A class for immutable linked lists representing ordered collections
* of elements of type `A`.
@@ -25,6 +25,8 @@ import java.io._
* This class is optimal for last-in-first-out (LIFO), stack-like access patterns. If you need another access
* pattern, for example, random access or FIFO, consider using a collection more suited to this than `List`.
*
+ * $usesMutableState
+ *
* ==Performance==
* '''Time:''' `List` has `O(1)` prepend and head/tail access. Most other operations are `O(n)` on the number of elements in the list.
* This includes the index-based lookup of elements, `length`, `append` and `reverse`.
@@ -86,11 +88,9 @@ sealed abstract class List[+A] extends AbstractSeq[A]
with Product
with GenericTraversableTemplate[A, List]
with LinearSeqOptimized[A, List[A]]
- with Serializable {
+ with scala.Serializable {
override def companion: GenericCompanion[List] = List
- import scala.collection.{Iterable, Traversable, Seq, IndexedSeq}
-
def isEmpty: Boolean
def head: A
def tail: List[A]
@@ -276,8 +276,7 @@ sealed abstract class List[+A] extends AbstractSeq[A]
}
(b.toList, these)
}
-
- @noinline // TODO - fix optimizer bug that requires noinline (see SI-8334)
+
final override def map[B, That](f: A => B)(implicit bf: CanBuildFrom[List[A], B, That]): That = {
if (bf eq List.ReusableCBF) {
if (this eq Nil) Nil.asInstanceOf[That] else {
@@ -295,8 +294,7 @@ sealed abstract class List[+A] extends AbstractSeq[A]
}
else super.map(f)
}
-
- @noinline // TODO - fix optimizer bug that requires noinline for map; applied here to be safe (see SI-8334)
+
final override def collect[B, That](pf: PartialFunction[A, B])(implicit bf: CanBuildFrom[List[A], B, That]): That = {
if (bf eq List.ReusableCBF) {
if (this eq Nil) Nil.asInstanceOf[That] else {
@@ -325,8 +323,7 @@ sealed abstract class List[+A] extends AbstractSeq[A]
}
else super.collect(pf)
}
-
- @noinline // TODO - fix optimizer bug that requires noinline for map; applied here to be safe (see SI-8334)
+
final override def flatMap[B, That](f: A => GenTraversableOnce[B])(implicit bf: CanBuildFrom[List[A], B, That]): That = {
if (bf eq List.ReusableCBF) {
if (this eq Nil) Nil.asInstanceOf[That] else {
@@ -414,7 +411,7 @@ sealed abstract class List[+A] extends AbstractSeq[A]
else new Stream.Cons(head, tail.toStream)
// Create a proxy for Java serialization that allows us to avoid mutation
- // during de-serialization. This is the Serialization Proxy Pattern.
+ // during deserialization. This is the Serialization Proxy Pattern.
protected final def writeReplace(): AnyRef = new List.SerializationProxy(this)
}
@@ -466,7 +463,7 @@ object List extends SeqFactory[List] {
override def empty[A]: List[A] = Nil
override def apply[A](xs: A*): List[A] = xs.toList
-
+
private[collection] val partialNotApplied = new Function1[Any, Any] { def apply(x: Any): Any = this }
@SerialVersionUID(1L)
@@ -482,7 +479,7 @@ object List extends SeqFactory[List] {
out.writeObject(ListSerializeEnd)
}
- // Java serialization calls this before readResolve during de-serialization.
+ // Java serialization calls this before readResolve during deserialization.
// Read the whole list and store it in `orig`.
private def readObject(in: ObjectInputStream) {
in.defaultReadObject()
diff --git a/src/library/scala/collection/immutable/ListMap.scala b/src/library/scala/collection/immutable/ListMap.scala
index 1eedf93269..589f8bbba9 100644
--- a/src/library/scala/collection/immutable/ListMap.scala
+++ b/src/library/scala/collection/immutable/ListMap.scala
@@ -6,202 +6,161 @@
** |/ **
\* */
-
-
package scala
package collection
package immutable
import generic._
-import scala.annotation.{tailrec, bridge}
-
-/** $factoryInfo
- * @since 1
- * @see [[http://docs.scala-lang.org/overviews/collections/concrete-immutable-collection-classes.html#list_maps "Scala's Collection Library overview"]]
- * section on `List Maps` for more information.
- *
- * @define Coll immutable.ListMap
- * @define coll immutable list map
- */
+import scala.annotation.tailrec
+
+/**
+ * $factoryInfo
+ *
+ * Note that each element insertion takes O(n) time, which means that creating a list map with
+ * n elements will take O(n^2^) time. This makes the builder suitable only for a small number of
+ * elements.
+ *
+ * @see [[http://docs.scala-lang.org/overviews/collections/concrete-immutable-collection-classes.html#list_maps "Scala's Collection Library overview"]]
+ * section on `List Maps` for more information.
+ * @since 1
+ * @define Coll ListMap
+ * @define coll list map
+ */
object ListMap extends ImmutableMapFactory[ListMap] {
- /** $mapCanBuildFromInfo */
+
+ /**
+ * $mapCanBuildFromInfo
+ */
implicit def canBuildFrom[A, B]: CanBuildFrom[Coll, (A, B), ListMap[A, B]] =
new MapCanBuildFrom[A, B]
+
def empty[A, B]: ListMap[A, B] = EmptyListMap.asInstanceOf[ListMap[A, B]]
- private object EmptyListMap extends ListMap[Any, Nothing] { }
+ @SerialVersionUID(-8256686706655863282L)
+ private object EmptyListMap extends ListMap[Any, Nothing]
}
-/** This class implements immutable maps using a list-based data structure, which preserves insertion order.
- * Instances of `ListMap` represent empty maps; they can be either created by
- * calling the constructor directly, or by applying the function `ListMap.empty`.
- *
- * @tparam A the type of the keys in this list map.
- * @tparam B the type of the values associated with the keys.
- *
- * @author Matthias Zenger
- * @author Martin Odersky
- * @version 2.0, 01/01/2007
- * @since 1
- * @define Coll immutable.ListMap
- * @define coll immutable list map
- * @define mayNotTerminateInf
- * @define willNotTerminateInf
- */
+/**
+ * This class implements immutable maps using a list-based data structure. List map iterators and
+ * traversal methods visit key-value pairs in the order whey were first inserted.
+ *
+ * Entries are stored internally in reversed insertion order, which means the newest key is at the
+ * head of the list. As such, methods such as `head` and `tail` are O(n), while `last` and `init`
+ * are O(1). Other operations, such as inserting or removing entries, are also O(n), which makes
+ * this collection suitable only for a small number of elements.
+ *
+ * Instances of `ListMap` represent empty maps; they can be either created by calling the
+ * constructor directly, or by applying the function `ListMap.empty`.
+ *
+ * @tparam A the type of the keys contained in this list map
+ * @tparam B the type of the values associated with the keys
+ *
+ * @author Matthias Zenger
+ * @author Martin Odersky
+ * @version 2.0, 01/01/2007
+ * @since 1
+ * @define Coll ListMap
+ * @define coll list map
+ * @define mayNotTerminateInf
+ * @define willNotTerminateInf
+ */
@SerialVersionUID(301002838095710379L)
-@deprecatedInheritance("The semantics of immutable collections makes inheriting from ListMap error-prone.", "2.11.0")
-class ListMap[A, +B]
-extends AbstractMap[A, B]
- with Map[A, B]
- with MapLike[A, B, ListMap[A, B]]
- with Serializable {
+sealed class ListMap[A, +B] extends AbstractMap[A, B]
+ with Map[A, B]
+ with MapLike[A, B, ListMap[A, B]]
+ with Serializable {
override def empty = ListMap.empty
- /** Returns the number of mappings in this map.
- *
- * @return number of mappings in this map.
- */
override def size: Int = 0
+ override def isEmpty: Boolean = true
- /** Checks if this map maps `key` to a value and return the
- * value if it exists.
- *
- * @param key the key of the mapping of interest
- * @return the value of the mapping, if it exists
- */
def get(key: A): Option[B] = None
- /** This method allows one to create a new map with an additional mapping
- * from `key` to `value`. If the map contains already a mapping for `key`,
- * it will be overridden by this function.
- *
- * @param key the key element of the updated entry.
- * @param value the value element of the updated entry.
- */
- override def updated [B1 >: B] (key: A, value: B1): ListMap[A, B1] =
- new Node[B1](key, value)
-
- /** Add a key/value pair to this map.
- * @param kv the key/value pair
- * @return A new map with the new binding added to this map
- */
- def + [B1 >: B] (kv: (A, B1)): ListMap[A, B1] = updated(kv._1, kv._2)
-
- /** Adds two or more elements to this collection and returns
- * either the collection itself (if it is mutable), or a new collection
- * with the added elements.
- *
- * @param elem1 the first element to add.
- * @param elem2 the second element to add.
- * @param elems the remaining elements to add.
- */
- override def + [B1 >: B] (elem1: (A, B1), elem2: (A, B1), elems: (A, B1) *): ListMap[A, B1] =
- this + elem1 + elem2 ++ elems
-
- /** Adds a number of elements provided by a traversable object
- * and returns a new collection with the added elements.
- *
- * @param xs the traversable object.
- */
+ override def updated[B1 >: B](key: A, value: B1): ListMap[A, B1] = new Node[B1](key, value)
+
+ def +[B1 >: B](kv: (A, B1)): ListMap[A, B1] = new Node[B1](kv._1, kv._2)
+ def -(key: A): ListMap[A, B] = this
+
override def ++[B1 >: B](xs: GenTraversableOnce[(A, B1)]): ListMap[A, B1] =
- ((repr: ListMap[A, B1]) /: xs.seq) (_ + _)
-
- /** This creates a new mapping without the given `key`.
- * If the map does not contain a mapping for the given key, the
- * method returns the same map.
- *
- * @param key a map without a mapping for the given key.
- */
- def - (key: A): ListMap[A, B] = this
-
- /** Returns an iterator over key-value pairs.
- */
- def iterator: Iterator[(A,B)] =
- new AbstractIterator[(A,B)] {
- var self: ListMap[A,B] = ListMap.this
- def hasNext = !self.isEmpty
- def next(): (A,B) =
- if (!hasNext) throw new NoSuchElementException("next on empty iterator")
- else { val res = (self.key, self.value); self = self.next; res }
- }.toList.reverseIterator
-
- protected def key: A = throw new NoSuchElementException("empty map")
- protected def value: B = throw new NoSuchElementException("empty map")
- protected def next: ListMap[A, B] = throw new NoSuchElementException("empty map")
-
- /** This class represents an entry in the `ListMap`.
- */
+ if (xs.isEmpty) this
+ else ((repr: ListMap[A, B1]) /: xs) (_ + _)
+
+ def iterator: Iterator[(A, B)] = {
+ def reverseList = {
+ var curr: ListMap[A, B] = this
+ var res: List[(A, B)] = Nil
+ while (!curr.isEmpty) {
+ res = (curr.key, curr.value) :: res
+ curr = curr.next
+ }
+ res
+ }
+ reverseList.iterator
+ }
+
+ protected def key: A = throw new NoSuchElementException("key of empty map")
+ protected def value: B = throw new NoSuchElementException("value of empty map")
+ protected def next: ListMap[A, B] = throw new NoSuchElementException("next of empty map")
+
+ override def stringPrefix = "ListMap"
+
+ /**
+ * Represents an entry in the `ListMap`.
+ */
@SerialVersionUID(-6453056603889598734L)
protected class Node[B1 >: B](override protected val key: A,
override protected val value: B1) extends ListMap[A, B1] with Serializable {
- /** Returns the number of mappings in this map.
- *
- * @return number of mappings.
- */
- override def size: Int = size0(this, 0)
-
- // to allow tail recursion and prevent stack overflows
- @tailrec private def size0(cur: ListMap[A, B1], acc: Int): Int = if (cur.isEmpty) acc else size0(cur.next, acc + 1)
-
- /** Is this an empty map?
- *
- * @return true, iff the map is empty.
- */
- override def isEmpty: Boolean = false
- /** Retrieves the value which is associated with the given key. This
- * method throws an exception if there is no mapping from the given
- * key to a value.
- *
- * @param k the key
- * @return the value associated with the given key.
- */
- override def apply(k: A): B1 = apply0(this, k)
+ override def size: Int = sizeInternal(this, 0)
+ @tailrec private[this] def sizeInternal(cur: ListMap[A, B1], acc: Int): Int =
+ if (cur.isEmpty) acc
+ else sizeInternal(cur.next, acc + 1)
- @tailrec private def apply0(cur: ListMap[A, B1], k: A): B1 =
- if (cur.isEmpty) throw new NoSuchElementException("key not found: "+k)
+ override def isEmpty: Boolean = false
+
+ override def apply(k: A): B1 = applyInternal(this, k)
+
+ @tailrec private[this] def applyInternal(cur: ListMap[A, B1], k: A): B1 =
+ if (cur.isEmpty) throw new NoSuchElementException("key not found: " + k)
else if (k == cur.key) cur.value
- else apply0(cur.next, k)
-
- /** Checks if this map maps `key` to a value and return the
- * value if it exists.
- *
- * @param k the key of the mapping of interest
- * @return the value of the mapping, if it exists
- */
- override def get(k: A): Option[B1] = get0(this, k)
-
- @tailrec private def get0(cur: ListMap[A, B1], k: A): Option[B1] =
- if (k == cur.key) Some(cur.value)
- else if (cur.next.nonEmpty) get0(cur.next, k) else None
-
- /** This method allows one to create a new map with an additional mapping
- * from `key` to `value`. If the map contains already a mapping for `key`,
- * it will be overridden by this function.
- */
- override def updated [B2 >: B1](k: A, v: B2): ListMap[A, B2] = {
+ else applyInternal(cur.next, k)
+
+ override def get(k: A): Option[B1] = getInternal(this, k)
+
+ @tailrec private[this] def getInternal(cur: ListMap[A, B1], k: A): Option[B1] =
+ if (cur.isEmpty) None
+ else if (k == cur.key) Some(cur.value)
+ else getInternal(cur.next, k)
+
+ override def contains(k: A): Boolean = containsInternal(this, k)
+
+ @tailrec private[this] def containsInternal(cur: ListMap[A, B1], k: A): Boolean =
+ if(cur.isEmpty) false
+ else if (k == cur.key) true
+ else containsInternal(cur.next, k)
+
+ override def updated[B2 >: B1](k: A, v: B2): ListMap[A, B2] = {
val m = this - k
new m.Node[B2](k, v)
}
- /** Creates a new mapping without the given `key`.
- * If the map does not contain a mapping for the given key, the
- * method returns the same map.
- */
- override def - (k: A): ListMap[A, B1] = remove0(k, this, Nil)
-
- @tailrec private def remove0(k: A, cur: ListMap[A, B1], acc: List[ListMap[A, B1]]): ListMap[A, B1] =
- if (cur.isEmpty)
- acc.last
- else if (k == cur.key)
- (cur.next /: acc) {
- case (t, h) => val tt = t; new tt.Node(h.key, h.value) // SI-7459
- }
- else
- remove0(k, cur.next, cur::acc)
+ override def +[B2 >: B1](kv: (A, B2)): ListMap[A, B2] = {
+ val m = this - kv._1
+ new m.Node[B2](kv._1, kv._2)
+ }
+
+ override def -(k: A): ListMap[A, B1] = removeInternal(k, this, Nil)
+
+ @tailrec private[this] def removeInternal(k: A, cur: ListMap[A, B1], acc: List[ListMap[A, B1]]): ListMap[A, B1] =
+ if (cur.isEmpty) acc.last
+ else if (k == cur.key) (cur.next /: acc) { case (t, h) => new t.Node(h.key, h.value) }
+ else removeInternal(k, cur.next, cur :: acc)
override protected def next: ListMap[A, B1] = ListMap.this
+
+ override def last: (A, B1) = (key, value)
+ override def init: ListMap[A, B1] = next
}
}
diff --git a/src/library/scala/collection/immutable/ListSet.scala b/src/library/scala/collection/immutable/ListSet.scala
index adc975479a..d9795e9161 100644
--- a/src/library/scala/collection/immutable/ListSet.scala
+++ b/src/library/scala/collection/immutable/ListSet.scala
@@ -11,174 +11,126 @@ package collection
package immutable
import generic._
-import scala.annotation.{tailrec, bridge}
-import mutable.{ ListBuffer, Builder }
-
-/** $factoryInfo
- * @define Coll immutable.ListSet
- * @define coll immutable list set
- * @since 1
- */
+import scala.annotation.tailrec
+
+/**
+ * $factoryInfo
+ *
+ * Note that each element insertion takes O(n) time, which means that creating a list set with
+ * n elements will take O(n^2^) time. This makes the builder suitable only for a small number of
+ * elements.
+ *
+ * @since 1
+ * @define Coll ListSet
+ * @define coll list set
+ */
object ListSet extends ImmutableSetFactory[ListSet] {
- /** setCanBuildFromInfo */
- implicit def canBuildFrom[A]: CanBuildFrom[Coll, A, ListSet[A]] = setCanBuildFrom[A]
- override def newBuilder[A]: Builder[A, ListSet[A]] = new ListSetBuilder[A]
+ /**
+ * $setCanBuildFromInfo
+ */
+ implicit def canBuildFrom[A]: CanBuildFrom[Coll, A, ListSet[A]] =
+ setCanBuildFrom[A]
- private object EmptyListSet extends ListSet[Any] { }
+ @SerialVersionUID(5010379588739277132L)
+ private object EmptyListSet extends ListSet[Any]
private[collection] def emptyInstance: ListSet[Any] = EmptyListSet
-
- /** A custom builder because forgetfully adding elements one at
- * a time to a list backed set puts the "squared" in N^2. There is a
- * temporary space cost, but it's improbable a list backed set could
- * become large enough for this to matter given its pricy element lookup.
- */
- class ListSetBuilder[Elem](initial: ListSet[Elem]) extends Builder[Elem, ListSet[Elem]] {
- def this() = this(empty[Elem])
- protected val elems = (new mutable.ListBuffer[Elem] ++= initial).reverse
- protected val seen = new mutable.HashSet[Elem] ++= initial
-
- def +=(x: Elem): this.type = {
- if (!seen(x)) {
- elems += x
- seen += x
- }
- this
- }
- def clear() = { elems.clear() ; seen.clear() }
- def result() = elems.foldLeft(empty[Elem])(_ unchecked_+ _)
- }
}
-/** This class implements immutable sets using a list-based data
- * structure. Instances of `ListSet` represent
- * empty sets; they can be either created by calling the constructor
- * directly, or by applying the function `ListSet.empty`.
- *
- * @tparam A the type of the elements contained in this list set.
- *
- * @author Matthias Zenger
- * @version 1.0, 09/07/2003
- * @since 1
- * @define Coll immutable.ListSet
- * @define coll immutable list set
- * @define mayNotTerminateInf
- * @define willNotTerminateInf
- */
-@deprecatedInheritance("The semantics of immutable collections makes inheriting from ListSet error-prone.", "2.11.0")
-class ListSet[A] extends AbstractSet[A]
- with Set[A]
- with GenericSetTemplate[A, ListSet]
- with SetLike[A, ListSet[A]]
- with Serializable{ self =>
+/**
+ * This class implements immutable sets using a list-based data structure. List set iterators and
+ * traversal methods visit elements in the order whey were first inserted.
+ *
+ * Elements are stored internally in reversed insertion order, which means the newest element is at
+ * the head of the list. As such, methods such as `head` and `tail` are O(n), while `last` and
+ * `init` are O(1). Other operations, such as inserting or removing entries, are also O(n), which
+ * makes this collection suitable only for a small number of elements.
+ *
+ * Instances of `ListSet` represent empty sets; they can be either created by calling the
+ * constructor directly, or by applying the function `ListSet.empty`.
+ *
+ * @tparam A the type of the elements contained in this list set
+ *
+ * @author Matthias Zenger
+ * @version 1.0, 09/07/2003
+ * @since 1
+ * @define Coll ListSet
+ * @define coll list set
+ * @define mayNotTerminateInf
+ * @define willNotTerminateInf
+ */
+@SerialVersionUID(-8417059026623606218L)
+sealed class ListSet[A] extends AbstractSet[A]
+ with Set[A]
+ with GenericSetTemplate[A, ListSet]
+ with SetLike[A, ListSet[A]]
+ with Serializable {
+
override def companion: GenericCompanion[ListSet] = ListSet
- /** Returns the number of elements in this set.
- *
- * @return number of set elements.
- */
override def size: Int = 0
override def isEmpty: Boolean = true
- /** Checks if this set contains element `elem`.
- *
- * @param elem the element to check for membership.
- * @return `'''true'''`, iff `elem` is contained in this set.
- */
def contains(elem: A): Boolean = false
- /** This method creates a new set with an additional element.
- */
- def + (elem: A): ListSet[A] = new Node(elem)
-
- /** `-` can be used to remove a single element.
- */
- def - (elem: A): ListSet[A] = this
+ def +(elem: A): ListSet[A] = new Node(elem)
+ def -(elem: A): ListSet[A] = this
- /** If we are bulk adding elements and desire a runtime measured in
- * sub-interstellar time units, we better find a way to avoid traversing
- * the collection on each element. That's what the custom builder does,
- * so we take the easy way out and add ourselves and the argument to
- * a new builder.
- */
override def ++(xs: GenTraversableOnce[A]): ListSet[A] =
if (xs.isEmpty) this
- else (new ListSet.ListSetBuilder(this) ++= xs.seq).result()
-
- private[ListSet] def unchecked_+(e: A): ListSet[A] = new Node(e)
- private[ListSet] def unchecked_outer: ListSet[A] =
- throw new NoSuchElementException("Empty ListSet has no outer pointer")
-
- /** Creates a new iterator over all elements contained in this set.
- *
- * @throws java.util.NoSuchElementException
- * @return the new iterator
- */
- def iterator: Iterator[A] = new AbstractIterator[A] {
- var that: ListSet[A] = self
- def hasNext = that.nonEmpty
- def next: A =
- if (hasNext) {
- val res = that.head
- that = that.tail
- res
+ else (repr /: xs) (_ + _)
+
+ def iterator: Iterator[A] = {
+ def reverseList = {
+ var curr: ListSet[A] = this
+ var res: List[A] = Nil
+ while (!curr.isEmpty) {
+ res = curr.elem :: res
+ curr = curr.next
}
- else Iterator.empty.next()
+ res
+ }
+ reverseList.iterator
}
- /**
- * @throws java.util.NoSuchElementException
- */
- override def head: A = throw new NoSuchElementException("Set has no elements")
+ protected def elem: A = throw new NoSuchElementException("elem of empty set")
+ protected def next: ListSet[A] = throw new NoSuchElementException("next of empty set")
- /**
- * @throws java.util.NoSuchElementException
- */
- override def tail: ListSet[A] = throw new NoSuchElementException("Next of an empty set")
+ override def toSet[B >: A]: Set[B] = this.asInstanceOf[ListSet[B]]
override def stringPrefix = "ListSet"
- /** Represents an entry in the `ListSet`.
- */
- protected class Node(override val head: A) extends ListSet[A] with Serializable {
- override private[ListSet] def unchecked_outer = self
+ /**
+ * Represents an entry in the `ListSet`.
+ */
+ @SerialVersionUID(-787710309854855049L)
+ protected class Node(override protected val elem: A) extends ListSet[A] with Serializable {
- /** Returns the number of elements in this set.
- *
- * @return number of set elements.
- */
override def size = sizeInternal(this, 0)
- @tailrec private def sizeInternal(n: ListSet[A], acc: Int): Int =
+
+ @tailrec private[this] def sizeInternal(n: ListSet[A], acc: Int): Int =
if (n.isEmpty) acc
- else sizeInternal(n.unchecked_outer, acc + 1)
+ else sizeInternal(n.next, acc + 1)
- /** Checks if this set is empty.
- *
- * @return true, iff there is no element in the set.
- */
override def isEmpty: Boolean = false
- /** Checks if this set contains element `elem`.
- *
- * @param e the element to check for membership.
- * @return `'''true'''`, iff `elem` is contained in this set.
- */
override def contains(e: A) = containsInternal(this, e)
- @tailrec private def containsInternal(n: ListSet[A], e: A): Boolean =
- !n.isEmpty && (n.head == e || containsInternal(n.unchecked_outer, e))
- /** This method creates a new set with an additional element.
- */
+ @tailrec private[this] def containsInternal(n: ListSet[A], e: A): Boolean =
+ !n.isEmpty && (n.elem == e || containsInternal(n.next, e))
+
override def +(e: A): ListSet[A] = if (contains(e)) this else new Node(e)
- /** `-` can be used to remove a single element from a set.
- */
- override def -(e: A): ListSet[A] = if (e == head) self else {
- val tail = self - e; new tail.Node(head)
- }
+ override def -(e: A): ListSet[A] = removeInternal(e, this, Nil)
+
+ @tailrec private[this] def removeInternal(k: A, cur: ListSet[A], acc: List[ListSet[A]]): ListSet[A] =
+ if (cur.isEmpty) acc.last
+ else if (k == cur.elem) (cur.next /: acc) { case (t, h) => new t.Node(h.elem) }
+ else removeInternal(k, cur.next, cur :: acc)
- override def tail: ListSet[A] = self
+ override protected def next: ListSet[A] = ListSet.this
+
+ override def last: A = elem
+ override def init: ListSet[A] = next
}
-
- override def toSet[B >: A]: Set[B] = this.asInstanceOf[ListSet[B]]
}
diff --git a/src/library/scala/collection/immutable/Map.scala b/src/library/scala/collection/immutable/Map.scala
index 2c5b444c70..4107b6414d 100644
--- a/src/library/scala/collection/immutable/Map.scala
+++ b/src/library/scala/collection/immutable/Map.scala
@@ -18,30 +18,30 @@ import generic._
* functionality for the abstract methods in `Map`:
*
* {{{
- * def get(key: A): Option[B]
- * def iterator: Iterator[(A, B)]
- * def + [B1 >: B](kv: (A, B1)): Map[A, B1]
- * def -(key: A): Map[A, B]
+ * def get(key: K): Option[V]
+ * def iterator: Iterator[(K, V)]
+ * def + [V1 >: V](kv: (K, V1)): Map[K, V1]
+ * def -(key: K): Map[K, V]
* }}}
*
* @since 1
*/
-trait Map[A, +B] extends Iterable[(A, B)]
-// with GenMap[A, B]
- with scala.collection.Map[A, B]
- with MapLike[A, B, Map[A, B]] { self =>
+trait Map[K, +V] extends Iterable[(K, V)]
+// with GenMap[K, V]
+ with scala.collection.Map[K, V]
+ with MapLike[K, V, Map[K, V]] { self =>
- override def empty: Map[A, B] = Map.empty
+ override def empty: Map[K, V] = Map.empty
/** Returns this $coll as an immutable map.
*
* A new map will not be built; lazy collections will stay lazy.
*/
@deprecatedOverriding("Immutable maps should do nothing on toMap except return themselves cast as a map.", "2.11.0")
- override def toMap[T, U](implicit ev: (A, B) <:< (T, U)): immutable.Map[T, U] =
+ override def toMap[T, U](implicit ev: (K, V) <:< (T, U)): immutable.Map[T, U] =
self.asInstanceOf[immutable.Map[T, U]]
- override def seq: Map[A, B] = this
+ override def seq: Map[K, V] = this
/** The same map with a given default function.
* Note: `get`, `contains`, `iterator`, `keys`, etc are not affected by `withDefault`.
@@ -51,7 +51,7 @@ trait Map[A, +B] extends Iterable[(A, B)]
* @param d the function mapping keys to values, used for non-present keys
* @return a wrapper of the map with a default value
*/
- def withDefault[B1 >: B](d: A => B1): immutable.Map[A, B1] = new Map.WithDefault[A, B1](this, d)
+ def withDefault[V1 >: V](d: K => V1): immutable.Map[K, V1] = new Map.WithDefault[K, V1](this, d)
/** The same map with a given default value.
* Note: `get`, `contains`, `iterator`, `keys`, etc are not affected by `withDefaultValue`.
@@ -61,15 +61,15 @@ trait Map[A, +B] extends Iterable[(A, B)]
* @param d default value used for non-present keys
* @return a wrapper of the map with a default value
*/
- def withDefaultValue[B1 >: B](d: B1): immutable.Map[A, B1] = new Map.WithDefault[A, B1](this, x => d)
+ def withDefaultValue[V1 >: V](d: V1): immutable.Map[K, V1] = new Map.WithDefault[K, V1](this, x => d)
/** Add a key/value pair to this map.
* @param key the key
* @param value the value
* @return A new map with the new binding added to this map
*/
- override def updated [B1 >: B](key: A, value: B1): Map[A, B1]
- def + [B1 >: B](kv: (A, B1)): Map[A, B1]
+ override def updated [V1 >: V](key: K, value: V1): Map[K, V1]
+ def + [V1 >: V](kv: (K, V1)): Map[K, V1]
}
/** $factoryInfo
@@ -79,116 +79,138 @@ trait Map[A, +B] extends Iterable[(A, B)]
object Map extends ImmutableMapFactory[Map] {
/** $mapCanBuildFromInfo */
- implicit def canBuildFrom[A, B]: CanBuildFrom[Coll, (A, B), Map[A, B]] = new MapCanBuildFrom[A, B]
+ implicit def canBuildFrom[K, V]: CanBuildFrom[Coll, (K, V), Map[K, V]] = new MapCanBuildFrom[K, V]
- def empty[A, B]: Map[A, B] = EmptyMap.asInstanceOf[Map[A, B]]
+ def empty[K, V]: Map[K, V] = EmptyMap.asInstanceOf[Map[K, V]]
- class WithDefault[A, +B](underlying: Map[A, B], d: A => B) extends scala.collection.Map.WithDefault[A, B](underlying, d) with Map[A, B] {
+ class WithDefault[K, +V](underlying: Map[K, V], d: K => V) extends scala.collection.Map.WithDefault[K, V](underlying, d) with Map[K, V] {
override def empty = new WithDefault(underlying.empty, d)
- override def updated[B1 >: B](key: A, value: B1): WithDefault[A, B1] = new WithDefault[A, B1](underlying.updated[B1](key, value), d)
- override def + [B1 >: B](kv: (A, B1)): WithDefault[A, B1] = updated(kv._1, kv._2)
- override def - (key: A): WithDefault[A, B] = new WithDefault(underlying - key, d)
- override def withDefault[B1 >: B](d: A => B1): immutable.Map[A, B1] = new WithDefault[A, B1](underlying, d)
- override def withDefaultValue[B1 >: B](d: B1): immutable.Map[A, B1] = new WithDefault[A, B1](underlying, x => d)
+ override def updated[V1 >: V](key: K, value: V1): WithDefault[K, V1] = new WithDefault[K, V1](underlying.updated[V1](key, value), d)
+ override def + [V1 >: V](kv: (K, V1)): WithDefault[K, V1] = updated(kv._1, kv._2)
+ override def - (key: K): WithDefault[K, V] = new WithDefault(underlying - key, d)
+ override def withDefault[V1 >: V](d: K => V1): immutable.Map[K, V1] = new WithDefault[K, V1](underlying, d)
+ override def withDefaultValue[V1 >: V](d: V1): immutable.Map[K, V1] = new WithDefault[K, V1](underlying, x => d)
}
private object EmptyMap extends AbstractMap[Any, Nothing] with Map[Any, Nothing] with Serializable {
override def size: Int = 0
+ override def apply(key: Any) = throw new NoSuchElementException("key not found: " + key)
+ override def contains(key: Any) = false
def get(key: Any): Option[Nothing] = None
def iterator: Iterator[(Any, Nothing)] = Iterator.empty
- override def updated [B1] (key: Any, value: B1): Map[Any, B1] = new Map1(key, value)
- def + [B1](kv: (Any, B1)): Map[Any, B1] = updated(kv._1, kv._2)
+ override def updated [V1] (key: Any, value: V1): Map[Any, V1] = new Map1(key, value)
+ def + [V1](kv: (Any, V1)): Map[Any, V1] = updated(kv._1, kv._2)
def - (key: Any): Map[Any, Nothing] = this
}
- class Map1[A, +B](key1: A, value1: B) extends AbstractMap[A, B] with Map[A, B] with Serializable {
+ class Map1[K, +V](key1: K, value1: V) extends AbstractMap[K, V] with Map[K, V] with Serializable {
override def size = 1
- def get(key: A): Option[B] =
+ override def apply(key: K) = if (key == key1) value1 else throw new NoSuchElementException("key not found: " + key)
+ override def contains(key: K) = key == key1
+ def get(key: K): Option[V] =
if (key == key1) Some(value1) else None
def iterator = Iterator((key1, value1))
- override def updated [B1 >: B] (key: A, value: B1): Map[A, B1] =
+ override def updated [V1 >: V] (key: K, value: V1): Map[K, V1] =
if (key == key1) new Map1(key1, value)
else new Map2(key1, value1, key, value)
- def + [B1 >: B](kv: (A, B1)): Map[A, B1] = updated(kv._1, kv._2)
- def - (key: A): Map[A, B] =
+ def + [V1 >: V](kv: (K, V1)): Map[K, V1] = updated(kv._1, kv._2)
+ def - (key: K): Map[K, V] =
if (key == key1) Map.empty else this
- override def foreach[U](f: ((A, B)) => U): Unit = {
+ override def foreach[U](f: ((K, V)) => U): Unit = {
f((key1, value1))
}
}
- class Map2[A, +B](key1: A, value1: B, key2: A, value2: B) extends AbstractMap[A, B] with Map[A, B] with Serializable {
+ class Map2[K, +V](key1: K, value1: V, key2: K, value2: V) extends AbstractMap[K, V] with Map[K, V] with Serializable {
override def size = 2
- def get(key: A): Option[B] =
+ override def apply(key: K) =
+ if (key == key1) value1
+ else if (key == key2) value2
+ else throw new NoSuchElementException("key not found: " + key)
+ override def contains(key: K) = (key == key1) || (key == key2)
+ def get(key: K): Option[V] =
if (key == key1) Some(value1)
else if (key == key2) Some(value2)
else None
def iterator = Iterator((key1, value1), (key2, value2))
- override def updated [B1 >: B] (key: A, value: B1): Map[A, B1] =
+ override def updated [V1 >: V] (key: K, value: V1): Map[K, V1] =
if (key == key1) new Map2(key1, value, key2, value2)
else if (key == key2) new Map2(key1, value1, key2, value)
else new Map3(key1, value1, key2, value2, key, value)
- def + [B1 >: B](kv: (A, B1)): Map[A, B1] = updated(kv._1, kv._2)
- def - (key: A): Map[A, B] =
+ def + [V1 >: V](kv: (K, V1)): Map[K, V1] = updated(kv._1, kv._2)
+ def - (key: K): Map[K, V] =
if (key == key1) new Map1(key2, value2)
else if (key == key2) new Map1(key1, value1)
else this
- override def foreach[U](f: ((A, B)) => U): Unit = {
+ override def foreach[U](f: ((K, V)) => U): Unit = {
f((key1, value1)); f((key2, value2))
}
}
- class Map3[A, +B](key1: A, value1: B, key2: A, value2: B, key3: A, value3: B) extends AbstractMap[A, B] with Map[A, B] with Serializable {
+ class Map3[K, +V](key1: K, value1: V, key2: K, value2: V, key3: K, value3: V) extends AbstractMap[K, V] with Map[K, V] with Serializable {
override def size = 3
- def get(key: A): Option[B] =
+ override def apply(key: K) =
+ if (key == key1) value1
+ else if (key == key2) value2
+ else if (key == key3) value3
+ else throw new NoSuchElementException("key not found: " + key)
+ override def contains(key: K) = (key == key1) || (key == key2) || (key == key3)
+ def get(key: K): Option[V] =
if (key == key1) Some(value1)
else if (key == key2) Some(value2)
else if (key == key3) Some(value3)
else None
def iterator = Iterator((key1, value1), (key2, value2), (key3, value3))
- override def updated [B1 >: B] (key: A, value: B1): Map[A, B1] =
+ override def updated [V1 >: V] (key: K, value: V1): Map[K, V1] =
if (key == key1) new Map3(key1, value, key2, value2, key3, value3)
else if (key == key2) new Map3(key1, value1, key2, value, key3, value3)
else if (key == key3) new Map3(key1, value1, key2, value2, key3, value)
else new Map4(key1, value1, key2, value2, key3, value3, key, value)
- def + [B1 >: B](kv: (A, B1)): Map[A, B1] = updated(kv._1, kv._2)
- def - (key: A): Map[A, B] =
+ def + [V1 >: V](kv: (K, V1)): Map[K, V1] = updated(kv._1, kv._2)
+ def - (key: K): Map[K, V] =
if (key == key1) new Map2(key2, value2, key3, value3)
else if (key == key2) new Map2(key1, value1, key3, value3)
else if (key == key3) new Map2(key1, value1, key2, value2)
else this
- override def foreach[U](f: ((A, B)) => U): Unit = {
+ override def foreach[U](f: ((K, V)) => U): Unit = {
f((key1, value1)); f((key2, value2)); f((key3, value3))
}
}
- class Map4[A, +B](key1: A, value1: B, key2: A, value2: B, key3: A, value3: B, key4: A, value4: B) extends AbstractMap[A, B] with Map[A, B] with Serializable {
+ class Map4[K, +V](key1: K, value1: V, key2: K, value2: V, key3: K, value3: V, key4: K, value4: V) extends AbstractMap[K, V] with Map[K, V] with Serializable {
override def size = 4
- def get(key: A): Option[B] =
+ override def apply(key: K) =
+ if (key == key1) value1
+ else if (key == key2) value2
+ else if (key == key3) value3
+ else if (key == key4) value4
+ else throw new NoSuchElementException("key not found: " + key)
+ override def contains(key: K) = (key == key1) || (key == key2) || (key == key3) || (key == key4)
+ def get(key: K): Option[V] =
if (key == key1) Some(value1)
else if (key == key2) Some(value2)
else if (key == key3) Some(value3)
else if (key == key4) Some(value4)
else None
def iterator = Iterator((key1, value1), (key2, value2), (key3, value3), (key4, value4))
- override def updated [B1 >: B] (key: A, value: B1): Map[A, B1] =
+ override def updated [V1 >: V] (key: K, value: V1): Map[K, V1] =
if (key == key1) new Map4(key1, value, key2, value2, key3, value3, key4, value4)
else if (key == key2) new Map4(key1, value1, key2, value, key3, value3, key4, value4)
else if (key == key3) new Map4(key1, value1, key2, value2, key3, value, key4, value4)
else if (key == key4) new Map4(key1, value1, key2, value2, key3, value3, key4, value)
- else new HashMap + ((key1, value1), (key2, value2), (key3, value3), (key4, value4), (key, value))
- def + [B1 >: B](kv: (A, B1)): Map[A, B1] = updated(kv._1, kv._2)
- def - (key: A): Map[A, B] =
+ else (new HashMap).updated(key1,value1).updated(key2, value2).updated(key3, value3).updated(key4, value4).updated(key, value)
+ def + [V1 >: V](kv: (K, V1)): Map[K, V1] = updated(kv._1, kv._2)
+ def - (key: K): Map[K, V] =
if (key == key1) new Map3(key2, value2, key3, value3, key4, value4)
else if (key == key2) new Map3(key1, value1, key3, value3, key4, value4)
else if (key == key3) new Map3(key1, value1, key2, value2, key4, value4)
else if (key == key4) new Map3(key1, value1, key2, value2, key3, value3)
else this
- override def foreach[U](f: ((A, B)) => U): Unit = {
+ override def foreach[U](f: ((K, V)) => U): Unit = {
f((key1, value1)); f((key2, value2)); f((key3, value3)); f((key4, value4))
}
}
}
/** Explicit instantiation of the `Map` trait to reduce class file size in subclasses. */
-abstract class AbstractMap[A, +B] extends scala.collection.AbstractMap[A, B] with Map[A, B]
+abstract class AbstractMap[K, +V] extends scala.collection.AbstractMap[K, V] with Map[K, V]
diff --git a/src/library/scala/collection/immutable/MapLike.scala b/src/library/scala/collection/immutable/MapLike.scala
index bd5b9c9faf..5867383b52 100644
--- a/src/library/scala/collection/immutable/MapLike.scala
+++ b/src/library/scala/collection/immutable/MapLike.scala
@@ -14,16 +14,16 @@ import generic._
import parallel.immutable.ParMap
/**
- * A generic template for immutable maps from keys of type `A`
- * to values of type `B`.
+ * A generic template for immutable maps from keys of type `K`
+ * to values of type `V`.
* To implement a concrete map, you need to provide implementations of the
* following methods (where `This` is the type of the actual map implementation):
*
* {{{
- * def get(key: A): Option[B]
- * def iterator: Iterator[(A, B)]
- * def + [B1 >: B](kv: (A, B)): Map[A, B1]
- * def - (key: A): This
+ * def get(key: K): Option[V]
+ * def iterator: Iterator[(K, V)]
+ * def + [V1 >: V](kv: (K, V)): Map[K, V1]
+ * def - (key: K): This
* }}}
*
* If you wish that transformer methods like `take`, `drop`, `filter` return the
@@ -36,8 +36,8 @@ import parallel.immutable.ParMap
* It is also good idea to override methods `foreach` and
* `size` for efficiency.
*
- * @tparam A the type of the keys contained in this collection.
- * @tparam B the type of the values associated with the keys.
+ * @tparam K the type of the keys contained in this collection.
+ * @tparam V the type of the values associated with the keys.
* @tparam This The type of the actual map implementation.
*
* @author Martin Odersky
@@ -46,26 +46,26 @@ import parallel.immutable.ParMap
* @define Coll immutable.Map
* @define coll immutable map
*/
-trait MapLike[A, +B, +This <: MapLike[A, B, This] with Map[A, B]]
- extends scala.collection.MapLike[A, B, This]
- with Parallelizable[(A, B), ParMap[A, B]]
+trait MapLike[K, +V, +This <: MapLike[K, V, This] with Map[K, V]]
+ extends scala.collection.MapLike[K, V, This]
+ with Parallelizable[(K, V), ParMap[K, V]]
{
self =>
- protected[this] override def parCombiner = ParMap.newCombiner[A, B]
+ protected[this] override def parCombiner = ParMap.newCombiner[K, V]
/** A new immutable map containing updating this map with a given key/value mapping.
* @param key the key
* @param value the value
* @return A new map with the new key/value mapping
*/
- override def updated [B1 >: B](key: A, value: B1): immutable.Map[A, B1] = this + ((key, value))
+ override def updated [V1 >: V](key: K, value: V1): immutable.Map[K, V1] = this + ((key, value))
/** Add a key/value pair to this map, returning a new map.
* @param kv the key/value pair.
* @return A new map with the new binding added to this map.
*/
- def + [B1 >: B] (kv: (A, B1)): immutable.Map[A, B1]
+ def + [V1 >: V] (kv: (K, V1)): immutable.Map[K, V1]
/** Adds two or more elements to this collection and returns
* a new collection.
@@ -75,7 +75,7 @@ self =>
* @param elems the remaining elements to add.
* @return A new map with the new bindings added to this map.
*/
- override def + [B1 >: B] (elem1: (A, B1), elem2: (A, B1), elems: (A, B1) *): immutable.Map[A, B1] =
+ override def + [V1 >: V] (elem1: (K, V1), elem2: (K, V1), elems: (K, V1) *): immutable.Map[K, V1] =
this + elem1 + elem2 ++ elems
/** Adds a number of elements provided by a traversable object
@@ -84,40 +84,40 @@ self =>
* @param xs the traversable object consisting of key-value pairs.
* @return a new immutable map with the bindings of this map and those from `xs`.
*/
- override def ++[B1 >: B](xs: GenTraversableOnce[(A, B1)]): immutable.Map[A, B1] =
- ((repr: immutable.Map[A, B1]) /: xs.seq) (_ + _)
+ override def ++[V1 >: V](xs: GenTraversableOnce[(K, V1)]): immutable.Map[K, V1] =
+ ((repr: immutable.Map[K, V1]) /: xs.seq) (_ + _)
/** Filters this map by retaining only keys satisfying a predicate.
* @param p the predicate used to test keys
* @return an immutable map consisting only of those key value pairs of this map where the key satisfies
* the predicate `p`. The resulting map wraps the original map without copying any elements.
*/
- override def filterKeys(p: A => Boolean): Map[A, B] = new FilteredKeys(p) with DefaultMap[A, B]
+ override def filterKeys(p: K => Boolean): Map[K, V] = new FilteredKeys(p) with DefaultMap[K, V]
/** Transforms this map by applying a function to every retrieved value.
* @param f the function used to transform values of this map.
* @return a map view which maps every key of this map
* to `f(this(key))`. The resulting map wraps the original map without copying any elements.
*/
- override def mapValues[C](f: B => C): Map[A, C] = new MappedValues(f) with DefaultMap[A, C]
+ override def mapValues[W](f: V => W): Map[K, W] = new MappedValues(f) with DefaultMap[K, W]
/** Collects all keys of this map in a set.
* @return a set containing all keys of this map.
*/
- override def keySet: immutable.Set[A] = new ImmutableDefaultKeySet
+ override def keySet: immutable.Set[K] = new ImmutableDefaultKeySet
- protected class ImmutableDefaultKeySet extends super.DefaultKeySet with immutable.Set[A] {
- override def + (elem: A): immutable.Set[A] =
+ protected class ImmutableDefaultKeySet extends super.DefaultKeySet with immutable.Set[K] {
+ override def + (elem: K): immutable.Set[K] =
if (this(elem)) this
- else immutable.Set[A]() ++ this + elem
- override def - (elem: A): immutable.Set[A] =
- if (this(elem)) immutable.Set[A]() ++ this - elem
+ else immutable.Set[K]() ++ this + elem
+ override def - (elem: K): immutable.Set[K] =
+ if (this(elem)) immutable.Set[K]() ++ this - elem
else this
// ImmutableDefaultKeySet is only protected, so we won't warn on override.
// Someone could override in a way that makes widening not okay
// (e.g. by overriding +, though the version in this class is fine)
- override def toSet[B >: A]: Set[B] = this.asInstanceOf[Set[B]]
+ override def toSet[B >: K]: Set[B] = this.asInstanceOf[Set[B]]
}
/** This function transforms all the values of mappings contained
@@ -126,10 +126,9 @@ self =>
* @param f A function over keys and values
* @return the updated map
*/
- def transform[C, That](f: (A, B) => C)(implicit bf: CanBuildFrom[This, (A, C), That]): That = {
+ def transform[W, That](f: (K, V) => W)(implicit bf: CanBuildFrom[This, (K, W), That]): That = {
val b = bf(repr)
for ((key, value) <- this) b += ((key, f(key, value)))
b.result()
}
}
-
diff --git a/src/library/scala/collection/immutable/MapProxy.scala b/src/library/scala/collection/immutable/MapProxy.scala
index d126b9e7a6..0d1c17d4b3 100644
--- a/src/library/scala/collection/immutable/MapProxy.scala
+++ b/src/library/scala/collection/immutable/MapProxy.scala
@@ -23,7 +23,7 @@ package immutable
* @version 2.0, 31/12/2006
* @since 2.8
*/
-@deprecated("Proxying is deprecated due to lack of use and compiler-level support.", "2.11.0")
+@deprecated("proxying is deprecated due to lack of use and compiler-level support", "2.11.0")
trait MapProxy[A, +B] extends Map[A, B] with MapProxyLike[A, B, Map[A, B]] {
override def repr = this
private def newProxy[B1 >: B](newSelf: Map[A, B1]): MapProxy[A, B1] =
diff --git a/src/library/scala/collection/immutable/NumericRange.scala b/src/library/scala/collection/immutable/NumericRange.scala
index 59b8a40c64..f1b831bf75 100644
--- a/src/library/scala/collection/immutable/NumericRange.scala
+++ b/src/library/scala/collection/immutable/NumericRange.scala
@@ -10,8 +10,6 @@ package scala
package collection
package immutable
-import mutable.{ Builder, ListBuffer }
-
// TODO: Now the specialization exists there is no clear reason to have
// separate classes for Range/NumericRange. Investigate and consolidate.
@@ -121,7 +119,7 @@ extends AbstractSeq[T] with IndexedSeq[T] with Serializable {
// (Integral <: Ordering). This can happen for custom Integral types.
// - The Ordering is the default Ordering of a well-known Integral type.
if ((ord eq num) || defaultOrdering.get(num).exists(ord eq _)) {
- if (num.signum(step) > 0) start
+ if (num.signum(step) > 0) head
else last
} else super.min(ord)
@@ -129,7 +127,7 @@ extends AbstractSeq[T] with IndexedSeq[T] with Serializable {
// See comment for fast path in min().
if ((ord eq num) || defaultOrdering.get(num).exists(ord eq _)) {
if (num.signum(step) > 0) last
- else start
+ else head
} else super.max(ord)
// Motivated by the desire for Double ranges with BigDecimal precision,
@@ -168,6 +166,12 @@ extends AbstractSeq[T] with IndexedSeq[T] with Serializable {
override def isEmpty = underlyingRange.isEmpty
override def apply(idx: Int): A = fm(underlyingRange(idx))
override def containsTyped(el: A) = underlyingRange exists (x => fm(x) == el)
+
+ override def toString = {
+ def simpleOf(x: Any): String = x.getClass.getName.split("\\.").last
+ val stepped = simpleOf(underlyingRange.step)
+ s"${super.toString} (using $underlyingRange of $stepped)"
+ }
}
}
@@ -198,7 +202,7 @@ extends AbstractSeq[T] with IndexedSeq[T] with Serializable {
// Either numRangeElements or (head + last) must be even, so divide the even one before multiplying
val a = head.toLong
val b = last.toLong
- val ans =
+ val ans =
if ((numRangeElements & 1) == 0) (numRangeElements / 2) * (a + b)
else numRangeElements * {
// Sum is even, but we might overflow it, so divide in pieces and add back remainder
@@ -257,9 +261,11 @@ extends AbstractSeq[T] with IndexedSeq[T] with Serializable {
super.equals(other)
}
- override def toString() = {
- val endStr = if (length > Range.MAX_PRINT) ", ... )" else ")"
- take(Range.MAX_PRINT).mkString("NumericRange(", ", ", endStr)
+ override def toString = {
+ val empty = if (isEmpty) "empty " else ""
+ val preposition = if (isInclusive) "to" else "until"
+ val stepped = if (step == 1) "" else s" by $step"
+ s"${empty}NumericRange $start $preposition $end$stepped"
}
}
diff --git a/src/library/scala/collection/immutable/PagedSeq.scala b/src/library/scala/collection/immutable/PagedSeq.scala
index 982c10687c..01854b1797 100644
--- a/src/library/scala/collection/immutable/PagedSeq.scala
+++ b/src/library/scala/collection/immutable/PagedSeq.scala
@@ -12,8 +12,7 @@ package scala
package collection
package immutable
-import java.io._
-import scala.util.matching.Regex
+import java.io.{File, FileReader, Reader}
import scala.reflect.ClassTag
/** The `PagedSeq` object defines a lazy implementations of
@@ -23,7 +22,7 @@ import scala.reflect.ClassTag
* `fromIterator` and `fromIterable` provide generalised instances of `PagedSeq`
* @since 2.7
*/
-@deprecated("This object will be moved to the scala-parser-combinators module", "2.11.8")
+@deprecated("this object will be moved to the scala-parser-combinators module", "2.11.8")
object PagedSeq {
final val UndeterminedEnd = Int.MaxValue
@@ -127,7 +126,7 @@ import PagedSeq._
* @define mayNotTerminateInf
* @define willNotTerminateInf
*/
-@deprecated("This class will be moved to the scala-parser-combinators module", "2.11.8")
+@deprecated("this class will be moved to the scala-parser-combinators module", "2.11.8")
class PagedSeq[T: ClassTag] protected(
more: (Array[T], Int, Int) => Int,
first1: Page[T],
diff --git a/src/library/scala/collection/immutable/Queue.scala b/src/library/scala/collection/immutable/Queue.scala
index 16cdc6d080..5081b39bdc 100644
--- a/src/library/scala/collection/immutable/Queue.scala
+++ b/src/library/scala/collection/immutable/Queue.scala
@@ -12,7 +12,6 @@ package immutable
import generic._
import mutable.{ Builder, ListBuffer }
-import scala.annotation.tailrec
/** `Queue` objects implement data structures that allow to
* insert and retrieve elements in a first-in-first-out (FIFO) manner.
@@ -38,8 +37,7 @@ import scala.annotation.tailrec
*/
@SerialVersionUID(-7622936493364270175L)
-@deprecatedInheritance("The implementation details of immutable queues make inheriting from them unwise.", "2.11.0")
-class Queue[+A] protected(protected val in: List[A], protected val out: List[A])
+sealed class Queue[+A] protected(protected val in: List[A], protected val out: List[A])
extends AbstractSeq[A]
with LinearSeq[A]
with GenericTraversableTemplate[A, Queue]
@@ -86,6 +84,14 @@ class Queue[+A] protected(protected val in: List[A], protected val out: List[A])
else if (in.nonEmpty) new Queue(Nil, in.reverse.tail)
else throw new NoSuchElementException("tail on empty queue")
+ /* This is made to avoid inefficient implementation of iterator. */
+ override def forall(p: A => Boolean): Boolean =
+ in.forall(p) && out.forall(p)
+
+ /* This is made to avoid inefficient implementation of iterator. */
+ override def exists(p: A => Boolean): Boolean =
+ in.exists(p) || out.exists(p)
+
/** Returns the length of the queue.
*/
override def length = in.length + out.length
@@ -100,6 +106,15 @@ class Queue[+A] protected(protected val in: List[A], protected val out: List[A])
case _ => super.:+(elem)(bf)
}
+ override def ++[B >: A, That](that: GenTraversableOnce[B])(implicit bf: CanBuildFrom[Queue[A], B, That]): That = {
+ if (bf eq Queue.ReusableCBF) {
+ val thatQueue = that.asInstanceOf[Queue[B]]
+ new Queue[B](thatQueue.in ++ (thatQueue.out reverse_::: this.in), this.out).asInstanceOf[That]
+ } else {
+ super.++(that)(bf)
+ }
+ }
+
/** Creates a new queue with element added at the end
* of the old queue.
*
diff --git a/src/library/scala/collection/immutable/Range.scala b/src/library/scala/collection/immutable/Range.scala
index ca6720da19..82203b3d1a 100644
--- a/src/library/scala/collection/immutable/Range.scala
+++ b/src/library/scala/collection/immutable/Range.scala
@@ -33,7 +33,7 @@ import scala.collection.parallel.immutable.ParRange
* `init`) are also permitted on overfull ranges.
*
* @param start the start of this range.
- * @param end the end of the range. For exclusive ranges, e.g.
+ * @param end the end of the range. For exclusive ranges, e.g.
* `Range(0,3)` or `(0 until 3)`, this is one
* step past the last one in the range. For inclusive
* ranges, e.g. `Range.inclusive(0,3)` or `(0 to 3)`,
@@ -57,8 +57,7 @@ import scala.collection.parallel.immutable.ParRange
* and its complexity is O(1).
*/
@SerialVersionUID(7618862778670199309L)
-@deprecatedInheritance("The implementation details of Range makes inheriting from it unwise.", "2.11.0")
-class Range(val start: Int, val end: Int, val step: Int)
+sealed class Range(val start: Int, val end: Int, val step: Int)
extends scala.collection.AbstractSeq[Int]
with IndexedSeq[Int]
with scala.collection.CustomParallelizable[Int, ParRange]
@@ -81,8 +80,8 @@ extends scala.collection.AbstractSeq[Int]
|| (start < end && step < 0)
|| (start == end && !isInclusive)
)
- @deprecated("This method will be made private, use `length` instead.", "2.11")
- final val numRangeElements: Int = {
+
+ private val numRangeElements: Int = {
if (step == 0) throw new IllegalArgumentException("step cannot be 0.")
else if (isEmpty) 0
else {
@@ -91,21 +90,17 @@ extends scala.collection.AbstractSeq[Int]
else len.toInt
}
}
- @deprecated("This method will be made private, use `last` instead.", "2.11")
- final val lastElement =
- if (isEmpty) start - step
- else step match {
- case 1 => if (isInclusive) end else end-1
- case -1 => if (isInclusive) end else end+1
- case _ =>
- val remainder = (gap % step).toInt
- if (remainder != 0) end - remainder
- else if (isInclusive) end
- else end - step
- }
-
- @deprecated("This method will be made private.", "2.11")
- final val terminalElement = lastElement + step
+
+ // This field has a sensible value only for non-empty ranges
+ private val lastElement = step match {
+ case 1 => if (isInclusive) end else end-1
+ case -1 => if (isInclusive) end else end+1
+ case _ =>
+ val remainder = (gap % step).toInt
+ if (remainder != 0) end - remainder
+ else if (isInclusive) end
+ else end - step
+ }
/** The last element of this range. This method will return the correct value
* even if there are too many elements to iterate over.
@@ -199,6 +194,23 @@ extends scala.collection.AbstractSeq[Int]
}
)
+ /** Creates a new range containing the elements starting at `from` up to but not including `until`.
+ *
+ * $doesNotUseBuilders
+ *
+ * @param from the element at which to start
+ * @param until the element at which to end (not included in the range)
+ * @return a new range consisting of a contiguous interval of values in the old range
+ */
+ override def slice(from: Int, until: Int): Range =
+ if (from <= 0) take(until)
+ else if (until >= numRangeElements && numRangeElements >= 0) drop(from)
+ else {
+ val fromValue = locationAfterN(from)
+ if (from >= until) newEmptyRange(fromValue)
+ else new Range.Inclusive(fromValue, locationAfterN(until-1), step)
+ }
+
/** Creates a new range containing all the elements of this range except the last one.
*
* $doesNotUseBuilders
@@ -380,22 +392,20 @@ extends scala.collection.AbstractSeq[Int]
case _ =>
super.equals(other)
}
- /** Note: hashCode can't be overridden without breaking Seq's
- * equals contract.
- */
- override def toString() = {
- val endStr =
- if (numRangeElements > Range.MAX_PRINT || (!isEmpty && numRangeElements < 0)) ", ... )" else ")"
- take(Range.MAX_PRINT).mkString("Range(", ", ", endStr)
+ /* Note: hashCode can't be overridden without breaking Seq's equals contract. */
+
+ override def toString = {
+ val preposition = if (isInclusive) "to" else "until"
+ val stepped = if (step == 1) "" else s" by $step"
+ val prefix = if (isEmpty) "empty " else if (!isExact) "inexact " else ""
+ s"${prefix}Range $start $preposition $end$stepped"
}
}
/** A companion object for the `Range` class.
*/
object Range {
- private[immutable] val MAX_PRINT = 512 // some arbitrary value
-
/** Counts the number of range elements.
* @pre step != 0
* If the size of the range exceeds Int.MaxValue, the
@@ -427,7 +437,7 @@ object Range {
def count(start: Int, end: Int, step: Int): Int =
count(start, end, step, isInclusive = false)
- class Inclusive(start: Int, end: Int, step: Int) extends Range(start, end, step) {
+ final class Inclusive(start: Int, end: Int, step: Int) extends Range(start, end, step) {
// override def par = new ParRange(this)
override def isInclusive = true
override protected def copy(start: Int, end: Int, step: Int): Range = new Inclusive(start, end, step)
@@ -496,8 +506,9 @@ object Range {
// As there is no appealing default step size for not-really-integral ranges,
// we offer a partially constructed object.
- class Partial[T, U](f: T => U) {
+ class Partial[T, U](private val f: T => U) extends AnyVal {
def by(x: T): U = f(x)
+ override def toString = "Range requires step"
}
// Illustrating genericity with Int Range, which should have the same behavior
diff --git a/src/library/scala/collection/immutable/Set.scala b/src/library/scala/collection/immutable/Set.scala
index 031e5248c1..0f16f97cb0 100644
--- a/src/library/scala/collection/immutable/Set.scala
+++ b/src/library/scala/collection/immutable/Set.scala
@@ -65,6 +65,7 @@ object Set extends ImmutableSetFactory[Set] {
implicit def canBuildFrom[A]: CanBuildFrom[Coll, A, Set[A]] = setCanBuildFrom[A]
/** An optimized representation for immutable empty sets */
+ @SerialVersionUID(-2443710944435909512L)
private object EmptySet extends AbstractSet[Any] with Set[Any] with Serializable {
override def size: Int = 0
def contains(elem: Any): Boolean = false
@@ -103,10 +104,11 @@ object Set extends ImmutableSetFactory[Set] {
if (p(elem1)) Some(elem1)
else None
}
+ override def head: A = elem1
+ override def tail: Set[A] = Set.empty
// Why is Set1 non-final? Need to fix that!
@deprecatedOverriding("This immutable set should do nothing on toSet but cast itself to a Set with a wider element type.", "2.11.8")
override def toSet[B >: A]: Set[B] = this.asInstanceOf[Set1[B]]
-
}
/** An optimized representation for immutable sets of size 2 */
@@ -138,6 +140,8 @@ object Set extends ImmutableSetFactory[Set] {
else if (p(elem2)) Some(elem2)
else None
}
+ override def head: A = elem1
+ override def tail: Set[A] = new Set1(elem2)
// Why is Set2 non-final? Need to fix that!
@deprecatedOverriding("This immutable set should do nothing on toSet but cast itself to a Set with a wider element type.", "2.11.8")
override def toSet[B >: A]: Set[B] = this.asInstanceOf[Set2[B]]
@@ -174,6 +178,8 @@ object Set extends ImmutableSetFactory[Set] {
else if (p(elem3)) Some(elem3)
else None
}
+ override def head: A = elem1
+ override def tail: Set[A] = new Set2(elem2, elem3)
// Why is Set3 non-final? Need to fix that!
@deprecatedOverriding("This immutable set should do nothing on toSet but cast itself to a Set with a wider element type.", "2.11.8")
override def toSet[B >: A]: Set[B] = this.asInstanceOf[Set3[B]]
@@ -187,7 +193,7 @@ object Set extends ImmutableSetFactory[Set] {
elem == elem1 || elem == elem2 || elem == elem3 || elem == elem4
def + (elem: A): Set[A] =
if (contains(elem)) this
- else new HashSet[A] + (elem1, elem2, elem3, elem4, elem)
+ else new HashSet[A] + elem1 + elem2 + elem3 + elem4 + elem
def - (elem: A): Set[A] =
if (elem == elem1) new Set3(elem2, elem3, elem4)
else if (elem == elem2) new Set3(elem1, elem3, elem4)
@@ -212,6 +218,8 @@ object Set extends ImmutableSetFactory[Set] {
else if (p(elem4)) Some(elem4)
else None
}
+ override def head: A = elem1
+ override def tail: Set[A] = new Set3(elem2, elem3, elem4)
// Why is Set4 non-final? Need to fix that!
@deprecatedOverriding("This immutable set should do nothing on toSet but cast itself to a Set with a wider element type.", "2.11.8")
override def toSet[B >: A]: Set[B] = this.asInstanceOf[Set4[B]]
diff --git a/src/library/scala/collection/immutable/SetProxy.scala b/src/library/scala/collection/immutable/SetProxy.scala
index d505185e1d..b421b48597 100644
--- a/src/library/scala/collection/immutable/SetProxy.scala
+++ b/src/library/scala/collection/immutable/SetProxy.scala
@@ -12,8 +12,7 @@ package scala
package collection
package immutable
-/** This is a simple wrapper class for <a href="Set.html"
- * target="contentFrame">`scala.collection.immutable.Set`</a>.
+/** This is a simple wrapper class for [[scala.collection.immutable.Set]].
*
* It is most useful for assembling customized set abstractions
* dynamically using object composition and forwarding.
@@ -22,7 +21,7 @@ package immutable
*
* @since 2.8
*/
-@deprecated("Proxying is deprecated due to lack of use and compiler-level support.", "2.11.0")
+@deprecated("proxying is deprecated due to lack of use and compiler-level support.", "2.11.0")
trait SetProxy[A] extends Set[A] with SetProxyLike[A, Set[A]] {
override def repr = this
private def newProxy[B >: A](newSelf: Set[B]): SetProxy[B] =
diff --git a/src/library/scala/collection/immutable/SortedMap.scala b/src/library/scala/collection/immutable/SortedMap.scala
index 682788e18e..0f3bd2e195 100644
--- a/src/library/scala/collection/immutable/SortedMap.scala
+++ b/src/library/scala/collection/immutable/SortedMap.scala
@@ -14,7 +14,6 @@ package immutable
import generic._
import mutable.Builder
-import scala.annotation.unchecked.uncheckedVariance
/** A map whose keys are sorted.
*
diff --git a/src/library/scala/collection/immutable/SortedSet.scala b/src/library/scala/collection/immutable/SortedSet.scala
index 4a8859a7ab..75b2b1f4dc 100644
--- a/src/library/scala/collection/immutable/SortedSet.scala
+++ b/src/library/scala/collection/immutable/SortedSet.scala
@@ -13,7 +13,6 @@ package collection
package immutable
import generic._
-import mutable.Builder
/** A subtrait of `collection.SortedSet` which represents sorted sets
* which cannot be mutated.
@@ -38,6 +37,6 @@ object SortedSet extends ImmutableSortedSetFactory[SortedSet] {
/** $sortedSetCanBuildFromInfo */
def canBuildFrom[A](implicit ord: Ordering[A]): CanBuildFrom[Coll, A, SortedSet[A]] = newCanBuildFrom[A]
def empty[A](implicit ord: Ordering[A]): SortedSet[A] = TreeSet.empty[A]
- // Force a declaration here so that BitSet's (which does not inherit from SortedSetFactory) can be more specific
+ // Force a declaration here so that BitSet (which does not inherit from SortedSetFactory) can be more specific
override implicit def newCanBuildFrom[A](implicit ord : Ordering[A]) : CanBuildFrom[Coll, A, SortedSet[A]] = super.newCanBuildFrom
}
diff --git a/src/library/scala/collection/immutable/Stack.scala b/src/library/scala/collection/immutable/Stack.scala
index 1c28093b2c..02bdadb5dd 100644
--- a/src/library/scala/collection/immutable/Stack.scala
+++ b/src/library/scala/collection/immutable/Stack.scala
@@ -46,7 +46,7 @@ object Stack extends SeqFactory[Stack] {
* @define willNotTerminateInf
*/
@SerialVersionUID(1976480595012942526L)
-@deprecated("Stack is an inelegant and potentially poorly-performing wrapper around List. Use List instead: stack push x becomes x :: list; stack.pop is list.tail.", "2.11.0")
+@deprecated("Stack is an inelegant and potentially poorly-performing wrapper around List. Use List instead: stack push x becomes x :: list; stack.pop is list.tail.", "2.11.0")
class Stack[+A] protected (protected val elems: List[A])
extends AbstractSeq[A]
with LinearSeq[A]
diff --git a/src/library/scala/collection/immutable/Stream.scala b/src/library/scala/collection/immutable/Stream.scala
index d3be809255..8f26de153a 100644
--- a/src/library/scala/collection/immutable/Stream.scala
+++ b/src/library/scala/collection/immutable/Stream.scala
@@ -11,7 +11,7 @@ package collection
package immutable
import generic._
-import mutable.{Builder, StringBuilder, LazyBuilder, ListBuffer}
+import mutable.{Builder, StringBuilder, LazyBuilder}
import scala.annotation.tailrec
import Stream.cons
import scala.language.implicitConversions
@@ -23,7 +23,7 @@ import scala.language.implicitConversions
* import scala.math.BigInt
* object Main extends App {
*
- * val fibs: Stream[BigInt] = BigInt(0) #:: BigInt(1) #:: fibs.zip(fibs.tail).map { n => n._1 + n._2 }
+ * lazy val fibs: Stream[BigInt] = BigInt(0) #:: BigInt(1) #:: fibs.zip(fibs.tail).map { n => n._1 + n._2 }
*
* fibs take 5 foreach println
* }
@@ -46,7 +46,7 @@ import scala.language.implicitConversions
* import scala.math.BigInt
* object Main extends App {
*
- * val fibs: Stream[BigInt] = BigInt(0) #:: BigInt(1) #:: fibs.zip(
+ * lazy val fibs: Stream[BigInt] = BigInt(0) #:: BigInt(1) #:: fibs.zip(
* fibs.tail).map(n => {
* println("Adding %d and %d".format(n._1, n._2))
* n._1 + n._2
@@ -162,7 +162,7 @@ import scala.language.implicitConversions
* // The first time we try to access the tail we're going to need more
* // information which will require us to recurse, which will require us to
* // recurse, which...
- * val sov: Stream[Vector[Int]] = Vector(0) #:: sov.zip(sov.tail).map { n => n._1 ++ n._2 }
+ * lazy val sov: Stream[Vector[Int]] = Vector(0) #:: sov.zip(sov.tail).map { n => n._1 ++ n._2 }
* }}}
*
* The definition of `fibs` above creates a larger number of objects than
@@ -198,16 +198,13 @@ import scala.language.implicitConversions
* @define orderDependentFold
* @define willTerminateInf Note: lazily evaluated; will terminate for infinite-sized collections.
*/
-@deprecatedInheritance("This class will be sealed.", "2.11.0")
-abstract class Stream[+A] extends AbstractSeq[A]
+sealed abstract class Stream[+A] extends AbstractSeq[A]
with LinearSeq[A]
with GenericTraversableTemplate[A, Stream]
with LinearSeqOptimized[A, Stream[A]]
- with Serializable {
-self =>
- override def companion: GenericCompanion[Stream] = Stream
+ with Serializable { self =>
- import scala.collection.{Traversable, Iterable, Seq, IndexedSeq}
+ override def companion: GenericCompanion[Stream] = Stream
/** Indicates whether or not the `Stream` is empty.
*
@@ -360,7 +357,7 @@ self =>
* `List(BigInt(12)) ++ fibs`.
*
* @tparam B The element type of the returned collection.'''That'''
- * @param that The [[scala.collection.GenTraversableOnce]] the be concatenated
+ * @param that The [[scala.collection.GenTraversableOnce]] to be concatenated
* to this `Stream`.
* @return A new collection containing the result of concatenating `this` with
* `that`.
@@ -499,80 +496,19 @@ self =>
)
else super.flatMap(f)(bf)
- /** Returns all the elements of this `Stream` that satisfy the predicate `p`
- * in a new `Stream` - i.e., it is still a lazy data structure. The order of
- * the elements is preserved
- *
- * @param p the predicate used to filter the stream.
- * @return the elements of this stream satisfying `p`.
- *
- * @example {{{
- * $naturalsEx
- * naturalsFrom(1) filter { _ % 5 == 0 } take 10 mkString(", ")
- * // produces "5, 10, 15, 20, 25, 30, 35, 40, 45, 50"
- * }}}
- */
- override def filter(p: A => Boolean): Stream[A] = {
+ override private[scala] def filterImpl(p: A => Boolean, isFlipped: Boolean): Stream[A] = {
// optimization: drop leading prefix of elems for which f returns false
// var rest = this dropWhile (!p(_)) - forget DRY principle - GC can't collect otherwise
var rest = this
- while (!rest.isEmpty && !p(rest.head)) rest = rest.tail
+ while (!rest.isEmpty && p(rest.head) == isFlipped) rest = rest.tail
// private utility func to avoid `this` on stack (would be needed for the lazy arg)
- if (rest.nonEmpty) Stream.filteredTail(rest, p)
+ if (rest.nonEmpty) Stream.filteredTail(rest, p, isFlipped)
else Stream.Empty
}
- override final def withFilter(p: A => Boolean): StreamWithFilter = new StreamWithFilter(p)
-
- /** A lazier implementation of WithFilter than TraversableLike's.
- */
- final class StreamWithFilter(p: A => Boolean) extends WithFilter(p) {
-
- override def map[B, That](f: A => B)(implicit bf: CanBuildFrom[Stream[A], B, That]): That = {
- def tailMap(coll: Stream[A]): Stream[B] = {
- var head: A = null.asInstanceOf[A]
- var tail: Stream[A] = coll
- while (true) {
- if (tail.isEmpty)
- return Stream.Empty
- head = tail.head
- tail = tail.tail
- if (p(head))
- return cons(f(head), tailMap(tail))
- }
- throw new RuntimeException()
- }
-
- if (isStreamBuilder(bf)) asThat(tailMap(Stream.this))
- else super.map(f)(bf)
- }
-
- override def flatMap[B, That](f: A => GenTraversableOnce[B])(implicit bf: CanBuildFrom[Stream[A], B, That]): That = {
- def tailFlatMap(coll: Stream[A]): Stream[B] = {
- var head: A = null.asInstanceOf[A]
- var tail: Stream[A] = coll
- while (true) {
- if (tail.isEmpty)
- return Stream.Empty
- head = tail.head
- tail = tail.tail
- if (p(head))
- return f(head).toStream append tailFlatMap(tail)
- }
- throw new RuntimeException()
- }
-
- if (isStreamBuilder(bf)) asThat(tailFlatMap(Stream.this))
- else super.flatMap(f)(bf)
- }
-
- override def foreach[U](f: A => U) =
- for (x <- self)
- if (p(x)) f(x)
-
- override def withFilter(q: A => Boolean): StreamWithFilter =
- new StreamWithFilter(x => p(x) && q(x))
- }
+ /** A FilterMonadic which allows GC of the head of stream during processing */
+ @noinline // Workaround SI-9137, see https://github.com/scala/scala/pull/4284#issuecomment-73180791
+ override final def withFilter(p: A => Boolean): FilterMonadic[A, Stream[A]] = new Stream.StreamWithFilter(this, p)
/** A lazier Iterator than LinearSeqLike's. */
override def iterator: Iterator[A] = new StreamIterator(self)
@@ -1093,6 +1029,8 @@ self =>
*/
override def stringPrefix = "Stream"
+ override def equals(that: Any): Boolean =
+ if (this eq that.asInstanceOf[AnyRef]) true else super.equals(that)
}
/** A specialized, extra-lazy implementation of a stream iterator, so it can
@@ -1152,14 +1090,12 @@ object Stream extends SeqFactory[Stream] {
/** Creates a new builder for a stream */
def newBuilder[A]: Builder[A, Stream[A]] = new StreamBuilder[A]
- import scala.collection.{Iterable, Seq, IndexedSeq}
-
/** A builder for streams
* @note This builder is lazy only in the sense that it does not go downs the spine
* of traversables that are added as a whole. If more laziness can be achieved,
* this builder should be bypassed.
*/
- class StreamBuilder[A] extends scala.collection.mutable.LazyBuilder[A, Stream[A]] {
+ class StreamBuilder[A] extends LazyBuilder[A, Stream[A]] {
def result: Stream[A] = parts.toStream flatMap (_.toStream)
}
@@ -1183,11 +1119,11 @@ object Stream extends SeqFactory[Stream] {
/** Construct a stream consisting of a given first element followed by elements
* from a lazily evaluated Stream.
*/
- def #::(hd: A): Stream[A] = cons(hd, tl)
+ def #::[B >: A](hd: B): Stream[B] = cons(hd, tl)
/** Construct a stream consisting of the concatenation of the given stream and
* a lazily evaluated Stream.
*/
- def #:::(prefix: Stream[A]): Stream[A] = prefix append tl
+ def #:::[B >: A](prefix: Stream[B]): Stream[B] = prefix append tl
}
/** A wrapper method that adds `#::` for cons and `#:::` for concat as operations
@@ -1237,6 +1173,27 @@ object Stream extends SeqFactory[Stream] {
tlVal
}
+
+ override /*LinearSeqOptimized*/
+ def sameElements[B >: A](that: GenIterable[B]): Boolean = {
+ @tailrec def consEq(a: Cons[_], b: Cons[_]): Boolean = {
+ if (a.head != b.head) false
+ else {
+ a.tail match {
+ case at: Cons[_] =>
+ b.tail match {
+ case bt: Cons[_] => (at eq bt) || consEq(at, bt)
+ case _ => false
+ }
+ case _ => b.tail.isEmpty
+ }
+ }
+ }
+ that match {
+ case that: Cons[_] => consEq(this, that)
+ case _ => super.sameElements(that)
+ }
+ }
}
/** An infinite stream that repeatedly applies a given function to a start value.
@@ -1295,13 +1252,36 @@ object Stream extends SeqFactory[Stream] {
else cons(start, range(start + step, end, step))
}
- private[immutable] def filteredTail[A](stream: Stream[A], p: A => Boolean) = {
- cons(stream.head, stream.tail filter p)
+ private[immutable] def filteredTail[A](stream: Stream[A], p: A => Boolean, isFlipped: Boolean) = {
+ cons(stream.head, stream.tail.filterImpl(p, isFlipped))
}
private[immutable] def collectedTail[A, B, That](head: B, stream: Stream[A], pf: PartialFunction[A, B], bf: CanBuildFrom[Stream[A], B, That]) = {
cons(head, stream.tail.collect(pf)(bf).asInstanceOf[Stream[B]])
}
-}
+ /** An implementation of `FilterMonadic` allowing GC of the filtered-out elements of
+ * the `Stream` as it is processed.
+ *
+ * Because this is not an inner class of `Stream` with a reference to the original
+ * head, it is now possible for GC to collect any leading and filtered-out elements
+ * which do not satisfy the filter, while the tail is still processing (see SI-8990).
+ */
+ private[immutable] final class StreamWithFilter[A](sl: => Stream[A], p: A => Boolean) extends FilterMonadic[A, Stream[A]] {
+ private var s = sl // set to null to allow GC after filtered
+ private lazy val filtered = { val f = s filter p; s = null; f } // don't set to null if throw during filter
+
+ def map[B, That](f: A => B)(implicit bf: CanBuildFrom[Stream[A], B, That]): That =
+ filtered map f
+
+ def flatMap[B, That](f: A => scala.collection.GenTraversableOnce[B])(implicit bf: CanBuildFrom[Stream[A], B, That]): That =
+ filtered flatMap f
+ def foreach[U](f: A => U): Unit =
+ filtered foreach f
+
+ def withFilter(q: A => Boolean): FilterMonadic[A, Stream[A]] =
+ new StreamWithFilter[A](filtered, q)
+ }
+
+}
diff --git a/src/library/scala/collection/immutable/StreamViewLike.scala b/src/library/scala/collection/immutable/StreamViewLike.scala
index c2eb85815d..4d7eaeff2a 100644
--- a/src/library/scala/collection/immutable/StreamViewLike.scala
+++ b/src/library/scala/collection/immutable/StreamViewLike.scala
@@ -53,6 +53,7 @@ extends SeqView[A, Coll]
/** boilerplate */
protected override def newForced[B](xs: => scala.collection.GenSeq[B]): Transformed[B] = new { val forced = xs } with AbstractTransformed[B] with Forced[B]
protected override def newAppended[B >: A](that: scala.collection.GenTraversable[B]): Transformed[B] = new { val rest = that } with AbstractTransformed[B] with Appended[B]
+ protected override def newPrepended[B >: A](that: scala.collection.GenTraversable[B]): Transformed[B] = new { protected[this] val fst = that } with AbstractTransformed[B] with Prepended[B]
protected override def newMapped[B](f: A => B): Transformed[B] = new { val mapping = f } with AbstractTransformed[B] with Mapped[B]
protected override def newFlatMapped[B](f: A => scala.collection.GenTraversableOnce[B]): Transformed[B] = new { val mapping = f } with AbstractTransformed[B] with FlatMapped[B]
protected override def newFiltered(p: A => Boolean): Transformed[A] = new { val pred = p } with AbstractTransformed[A] with Filtered
@@ -67,7 +68,6 @@ extends SeqView[A, Coll]
protected override def newPatched[B >: A](_from: Int, _patch: scala.collection.GenSeq[B], _replaced: Int): Transformed[B] = {
new { val from = _from; val patch = _patch; val replaced = _replaced } with AbstractTransformed[B] with Patched[B]
}
- protected override def newPrepended[B >: A](elem: B): Transformed[B] = new { protected[this] val fst = elem } with AbstractTransformed[B] with Prepended[B]
override def stringPrefix = "StreamView"
}
diff --git a/src/library/scala/collection/immutable/StringLike.scala b/src/library/scala/collection/immutable/StringLike.scala
index 232d67df4f..fce0f073aa 100644
--- a/src/library/scala/collection/immutable/StringLike.scala
+++ b/src/library/scala/collection/immutable/StringLike.scala
@@ -10,7 +10,7 @@ package scala
package collection
package immutable
-import mutable.{ ArrayBuilder, Builder }
+import mutable.Builder
import scala.util.matching.Regex
import scala.math.ScalaNumber
import scala.reflect.ClassTag
@@ -100,11 +100,13 @@ self =>
/** Return all lines in this string in an iterator, including trailing
* line end characters.
*
- * The number of strings returned is one greater than the number of line
- * end characters in this string. For an empty string, a single empty
- * line is returned. A line end character is one of
- * - `LF` - line feed (`0x0A` hex)
- * - `FF` - form feed (`0x0C` hex)
+ * This method is analogous to `s.split(EOL).toIterator`,
+ * except that any existing line endings are preserved in the result strings,
+ * and the empty string yields an empty iterator.
+ *
+ * A line end character is one of
+ * - `LF` - line feed (`0x0A`)
+ * - `FF` - form feed (`0x0C`)
*/
def linesWithSeparators: Iterator[String] = new AbstractIterator[String] {
val str = self.toString
@@ -121,17 +123,17 @@ self =>
}
/** Return all lines in this string in an iterator, excluding trailing line
- * end characters, i.e., apply `.stripLineEnd` to all lines
+ * end characters; i.e., apply `.stripLineEnd` to all lines
* returned by `linesWithSeparators`.
*/
def lines: Iterator[String] =
linesWithSeparators map (line => new WrappedString(line).stripLineEnd)
/** Return all lines in this string in an iterator, excluding trailing line
- * end characters, i.e., apply `.stripLineEnd` to all lines
+ * end characters; i.e., apply `.stripLineEnd` to all lines
* returned by `linesWithSeparators`.
*/
- @deprecated("Use `lines` instead.","2.11.0")
+ @deprecated("use `lines` instead","2.11.0")
def linesIterator: Iterator[String] =
linesWithSeparators map (line => new WrappedString(line).stripLineEnd)
@@ -163,20 +165,14 @@ self =>
if (toString.endsWith(suffix)) toString.substring(0, toString.length() - suffix.length)
else toString
- /** Replace all literal occurrences of `literal` with the string `replacement`.
- * This is equivalent to [[java.lang.String#replaceAll]] except that both arguments
- * are appropriately quoted to avoid being interpreted as metacharacters.
+ /** Replace all literal occurrences of `literal` with the literal string `replacement`.
+ * This method is equivalent to [[java.lang.String#replace]].
*
* @param literal the string which should be replaced everywhere it occurs
* @param replacement the replacement string
* @return the resulting string
*/
- def replaceAllLiterally(literal: String, replacement: String): String = {
- val arg1 = Regex.quote(literal)
- val arg2 = Regex.quoteReplacement(replacement)
-
- toString.replaceAll(arg1, arg2)
- }
+ def replaceAllLiterally(literal: String, replacement: String): String = toString.replace(literal, replacement)
/** For every line in this string:
*
@@ -202,35 +198,64 @@ self =>
*/
def stripMargin: String = stripMargin('|')
- private def escape(ch: Char): String = "\\Q" + ch + "\\E"
-
- def split(separator: Char): Array[String] = {
- val thisString = toString
- var pos = thisString.indexOf(separator)
-
- if (pos != -1) {
- val res = new ArrayBuilder.ofRef[String]
-
- var prev = 0
- do {
- res += thisString.substring(prev, pos)
- prev = pos + 1
- pos = thisString.indexOf(separator, prev)
- } while (pos != -1)
-
- if (prev != thisString.length)
- res += thisString.substring(prev, thisString.length)
-
- val initialResult = res.result()
- pos = initialResult.length
- while (pos > 0 && initialResult(pos - 1).isEmpty) pos = pos - 1
- if (pos != initialResult.length) {
- val trimmed = new Array[String](pos)
- Array.copy(initialResult, 0, trimmed, 0, pos)
- trimmed
- } else initialResult
- } else Array[String](thisString)
- }
+ private def escape(ch: Char): String = if (
+ (ch >= 'a') && (ch <= 'z') ||
+ (ch >= 'A') && (ch <= 'Z') ||
+ (ch >= '0' && ch <= '9')) ch.toString
+ else "\\" + ch
+
+ /** Split this string around the separator character
+ *
+ * If this string is the empty string, returns an array of strings
+ * that contains a single empty string.
+ *
+ * If this string is not the empty string, returns an array containing
+ * the substrings terminated by the start of the string, the end of the
+ * string or the separator character, excluding empty trailing substrings
+ *
+ * If the separator character is a surrogate character, only split on
+ * matching surrogate characters if they are not part of a surrogate pair
+ *
+ * The behaviour follows, and is implemented in terms of <a href="http://docs.oracle.com/javase/7/docs/api/java/lang/String.html#split%28java.lang.String%29">String.split(re: String)</a>
+ *
+ *
+ * @example {{{
+ * "a.b".split('.') //returns Array("a", "b")
+ *
+ * //splitting the empty string always returns the array with a single
+ * //empty string
+ * "".split('.') //returns Array("")
+ *
+ * //only trailing empty substrings are removed
+ * "a.".split('.') //returns Array("a")
+ * ".a.".split('.') //returns Array("", "a")
+ * "..a..".split('.') //returns Array("", "", "a")
+ *
+ * //all parts are empty and trailing
+ * ".".split('.') //returns Array()
+ * "..".split('.') //returns Array()
+ *
+ * //surrogate pairs
+ * val high = 0xD852.toChar
+ * val low = 0xDF62.toChar
+ * val highstring = high.toString
+ * val lowstring = low.toString
+ *
+ * //well-formed surrogate pairs are not split
+ * val highlow = highstring + lowstring
+ * highlow.split(high) //returns Array(highlow)
+ *
+ * //bare surrogate characters are split
+ * val bare = "_" + highstring + "_"
+ * bare.split(high) //returns Array("_", "_")
+ *
+ * }}}
+ *
+ * @param separator the character used as a delimiter
+ */
+ def split(separator: Char): Array[String] =
+ toString.split(escape(separator))
+
@throws(classOf[java.util.regex.PatternSyntaxException])
def split(separators: Array[Char]): Array[String] = {
@@ -256,31 +281,39 @@ self =>
def r(groupNames: String*): Regex = new Regex(toString, groupNames: _*)
/**
- * @throws java.lang.IllegalArgumentException - If the string does not contain a parsable boolean.
+ * @throws java.lang.IllegalArgumentException If the string does not contain a parsable `Boolean`.
*/
def toBoolean: Boolean = parseBoolean(toString)
/**
- * @throws java.lang.NumberFormatException - If the string does not contain a parsable byte.
+ * Parse as a `Byte` (string must contain only decimal digits and optional leading `-`).
+ * @throws java.lang.NumberFormatException If the string does not contain a parsable `Byte`.
*/
def toByte: Byte = java.lang.Byte.parseByte(toString)
/**
- * @throws java.lang.NumberFormatException - If the string does not contain a parsable short.
+ * Parse as a `Short` (string must contain only decimal digits and optional leading `-`).
+ * @throws java.lang.NumberFormatException If the string does not contain a parsable `Short`.
*/
def toShort: Short = java.lang.Short.parseShort(toString)
/**
- * @throws java.lang.NumberFormatException - If the string does not contain a parsable int.
+ * Parse as an `Int` (string must contain only decimal digits and optional leading `-`).
+ * @throws java.lang.NumberFormatException If the string does not contain a parsable `Int`.
*/
def toInt: Int = java.lang.Integer.parseInt(toString)
/**
- * @throws java.lang.NumberFormatException - If the string does not contain a parsable long.
+ * Parse as a `Long` (string must contain only decimal digits and optional leading `-`).
+ * @throws java.lang.NumberFormatException If the string does not contain a parsable `Long`.
*/
def toLong: Long = java.lang.Long.parseLong(toString)
/**
- * @throws java.lang.NumberFormatException - If the string does not contain a parsable float.
+ * Parse as a `Float` (surrounding whitespace is removed with a `trim`).
+ * @throws java.lang.NumberFormatException If the string does not contain a parsable `Float`.
+ * @throws java.lang.NullPointerException If the string is null.
*/
def toFloat: Float = java.lang.Float.parseFloat(toString)
/**
- * @throws java.lang.NumberFormatException - If the string does not contain a parsable double.
+ * Parse as a `Double` (surrounding whitespace is removed with a `trim`).
+ * @throws java.lang.NumberFormatException If the string does not contain a parsable `Double`.
+ * @throws java.lang.NullPointerException If the string is null.
*/
def toDouble: Double = java.lang.Double.parseDouble(toString)
@@ -306,8 +339,7 @@ self =>
* holes.
*
* The interpretation of the formatting patterns is described in
- * <a href="" target="contentFrame" class="java/util/Formatter">
- * `java.util.Formatter`</a>, with the addition that
+ * [[java.util.Formatter]], with the addition that
* classes deriving from `ScalaNumber` (such as [[scala.BigInt]] and
* [[scala.BigDecimal]]) are unwrapped to pass a type which `Formatter`
* understands.
@@ -322,8 +354,7 @@ self =>
* which influences formatting as in `java.lang.String`'s format.
*
* The interpretation of the formatting patterns is described in
- * <a href="" target="contentFrame" class="java/util/Formatter">
- * `java.util.Formatter`</a>, with the addition that
+ * [[java.util.Formatter]], with the addition that
* classes deriving from `ScalaNumber` (such as `scala.BigInt` and
* `scala.BigDecimal`) are unwrapped to pass a type which `Formatter`
* understands.
diff --git a/src/library/scala/collection/immutable/Traversable.scala b/src/library/scala/collection/immutable/Traversable.scala
index 5fc0607a00..3d4ba95a16 100644
--- a/src/library/scala/collection/immutable/Traversable.scala
+++ b/src/library/scala/collection/immutable/Traversable.scala
@@ -18,6 +18,17 @@ import mutable.Builder
/** A trait for traversable collections that are guaranteed immutable.
* $traversableInfo
* @define mutability immutable
+ *
+ * @define usesMutableState
+ *
+ * Note: Despite being an immutable collection, the implementation uses mutable state internally during
+ * construction. These state changes are invisible in single-threaded code but can lead to race conditions
+ * in some multi-threaded scenarios. The state of a new collection instance may not have been "published"
+ * (in the sense of the Java Memory Model specification), so that an unsynchronized non-volatile read from
+ * another thread may observe the object in an invalid state (see
+ * [[https://issues.scala-lang.org/browse/SI-7838 SI-7838]] for details). Note that such a read is not
+ * guaranteed to ''ever'' see the written object at all, and should therefore not be used, regardless
+ * of this issue. The easiest workaround is to exchange values between threads through a volatile var.
*/
trait Traversable[+A] extends scala.collection.Traversable[A]
// with GenTraversable[A]
diff --git a/src/library/scala/collection/immutable/TreeMap.scala b/src/library/scala/collection/immutable/TreeMap.scala
index b845b76026..2d1bf0f6b1 100644
--- a/src/library/scala/collection/immutable/TreeMap.scala
+++ b/src/library/scala/collection/immutable/TreeMap.scala
@@ -44,8 +44,7 @@ object TreeMap extends ImmutableSortedMapFactory[TreeMap] {
* @define mayNotTerminateInf
* @define willNotTerminateInf
*/
-@deprecatedInheritance("The implementation details of immutable tree maps make inheriting from them unwise.", "2.11.0")
-class TreeMap[A, +B] private (tree: RB.Tree[A, B])(implicit val ordering: Ordering[A])
+final class TreeMap[A, +B] private (tree: RB.Tree[A, B])(implicit val ordering: Ordering[A])
extends SortedMap[A, B]
with SortedMapLike[A, B, TreeMap[A, B]]
with MapLike[A, B, TreeMap[A, B]]
diff --git a/src/library/scala/collection/immutable/TreeSet.scala b/src/library/scala/collection/immutable/TreeSet.scala
index 2800030d67..2cdf3b3521 100644
--- a/src/library/scala/collection/immutable/TreeSet.scala
+++ b/src/library/scala/collection/immutable/TreeSet.scala
@@ -49,8 +49,7 @@ object TreeSet extends ImmutableSortedSetFactory[TreeSet] {
* @define willNotTerminateInf
*/
@SerialVersionUID(-5685982407650748405L)
-@deprecatedInheritance("The implementation details of immutable tree sets make inheriting from them unwise.", "2.11.0")
-class TreeSet[A] private (tree: RB.Tree[A, Unit])(implicit val ordering: Ordering[A])
+final class TreeSet[A] private (tree: RB.Tree[A, Unit])(implicit val ordering: Ordering[A])
extends SortedSet[A] with SortedSetLike[A, TreeSet[A]] with Serializable {
if (ordering eq null)
diff --git a/src/library/scala/collection/immutable/Vector.scala b/src/library/scala/collection/immutable/Vector.scala
index 5a9734a99e..1093084b9d 100644
--- a/src/library/scala/collection/immutable/Vector.scala
+++ b/src/library/scala/collection/immutable/Vector.scala
@@ -11,9 +11,8 @@ package collection
package immutable
import scala.annotation.unchecked.uncheckedVariance
-import scala.compat.Platform
import scala.collection.generic._
-import scala.collection.mutable.Builder
+import scala.collection.mutable.{Builder, ReusableBuilder}
import scala.collection.parallel.immutable.ParVector
/** Companion object to the Vector class
@@ -24,7 +23,7 @@ object Vector extends IndexedSeqFactory[Vector] {
ReusableCBF.asInstanceOf[GenericCanBuildFrom[A]]
private[immutable] val NIL = new Vector[Nothing](0, 0, 0)
override def empty[A]: Vector[A] = NIL
-
+
// Constants governing concat strategy for performance
private final val Log2ConcatFaster = 5
private final val TinyAppendFaster = 2
@@ -40,6 +39,8 @@ object Vector extends IndexedSeqFactory[Vector] {
* endian bit-mapped vector trie with a branching factor of 32. Locality is very good, but not
* contiguous, which is good for very large sequences.
*
+ * $usesMutableState
+ *
* @see [[http://docs.scala-lang.org/overviews/collections/concrete-immutable-collection-classes.html#vectors "Scala's Collection Library overview"]]
* section on `Vectors` for more information.
*
@@ -59,6 +60,7 @@ object Vector extends IndexedSeqFactory[Vector] {
* @define mayNotTerminateInf
* @define willNotTerminateInf
*/
+@SerialVersionUID(-1334388273712300479L)
final class Vector[+A] private[immutable] (private[collection] val startIndex: Int, private[collection] val endIndex: Int, focus: Int)
extends AbstractSeq[A]
with IndexedSeq[A]
@@ -69,12 +71,7 @@ extends AbstractSeq[A]
with CustomParallelizable[A, ParVector[A]]
{ self =>
-override def companion: GenericCompanion[Vector] = Vector
-
- //assert(startIndex >= 0, startIndex+"<0")
- //assert(startIndex <= endIndex, startIndex+">"+endIndex)
- //assert(focus >= 0, focus+"<0")
- //assert(focus <= endIndex, focus+">"+endIndex)
+ override def companion: GenericCompanion[Vector] = Vector
private[immutable] var dirty = false
@@ -98,8 +95,6 @@ override def companion: GenericCompanion[Vector] = Vector
s
}
-
- // can still be improved
override /*SeqLike*/
def reverseIterator: Iterator[A] = new AbstractIterator[A] {
private var i = self.length
@@ -111,22 +106,18 @@ override def companion: GenericCompanion[Vector] = Vector
} else Iterator.empty.next()
}
- // TODO: reverse
-
- // TODO: check performance of foreach/map etc. should override or not?
// Ideally, clients will inline calls to map all the way down, including the iterator/builder methods.
// In principle, escape analysis could even remove the iterator/builder allocations and do it
// with local variables exclusively. But we're not quite there yet ...
def apply(index: Int): A = {
val idx = checkRangeConvert(index)
- //println("get elem: "+index + "/"+idx + "(focus:" +focus+" xor:"+(idx^focus)+" depth:"+depth+")")
getElem(idx, idx ^ focus)
}
private def checkRangeConvert(index: Int) = {
val idx = index + startIndex
- if (0 <= index && idx < endIndex)
+ if (index >= 0 && idx < endIndex)
idx
else
throw new IndexOutOfBoundsException(index.toString)
@@ -135,7 +126,7 @@ override def companion: GenericCompanion[Vector] = Vector
// If we have a default builder, there are faster ways to perform some operations
@inline private[this] def isDefaultCBF[A, B, That](bf: CanBuildFrom[Vector[A], B, That]): Boolean =
(bf eq IndexedSeq.ReusableCBF) || (bf eq collection.immutable.Seq.ReusableCBF) || (bf eq collection.Seq.ReusableCBF)
-
+
// SeqLike api
override def updated[B >: A, That](index: Int, elem: B)(implicit bf: CanBuildFrom[Vector[A], B, That]): That =
@@ -189,31 +180,36 @@ override def companion: GenericCompanion[Vector] = Vector
Vector.empty
}
- override /*IterableLike*/ def head: A = {
+ override /*IterableLike*/
+ def head: A = {
if (isEmpty) throw new UnsupportedOperationException("empty.head")
apply(0)
}
- override /*TraversableLike*/ def tail: Vector[A] = {
+ override /*TraversableLike*/
+ def tail: Vector[A] = {
if (isEmpty) throw new UnsupportedOperationException("empty.tail")
drop(1)
}
- override /*TraversableLike*/ def last: A = {
+ override /*TraversableLike*/
+ def last: A = {
if (isEmpty) throw new UnsupportedOperationException("empty.last")
- apply(length-1)
+ apply(length - 1)
}
- override /*TraversableLike*/ def init: Vector[A] = {
+ override /*TraversableLike*/
+ def init: Vector[A] = {
if (isEmpty) throw new UnsupportedOperationException("empty.init")
dropRight(1)
}
- override /*IterableLike*/ def slice(from: Int, until: Int): Vector[A] =
+ override /*IterableLike*/
+ def slice(from: Int, until: Int): Vector[A] =
take(until).drop(from)
- override /*IterableLike*/ def splitAt(n: Int): (Vector[A], Vector[A]) = (take(n), drop(n))
-
+ override /*IterableLike*/
+ def splitAt(n: Int): (Vector[A], Vector[A]) = (take(n), drop(n))
// concat (suboptimal but avoids worst performance gotchas)
override def ++[B >: A, That](that: GenTraversableOnce[B])(implicit bf: CanBuildFrom[Vector[A], B, That]): That = {
@@ -225,11 +221,11 @@ override def companion: GenericCompanion[Vector] = Vector
val again = if (!that.isTraversableAgain) that.toVector else that.seq
again.size match {
// Often it's better to append small numbers of elements (or prepend if RHS is a vector)
- case n if n <= TinyAppendFaster || n < (this.size >> Log2ConcatFaster) =>
+ case n if n <= TinyAppendFaster || n < (this.size >>> Log2ConcatFaster) =>
var v: Vector[B] = this
for (x <- again) v = v :+ x
v.asInstanceOf[That]
- case n if this.size < (n >> Log2ConcatFaster) && again.isInstanceOf[Vector[_]] =>
+ case n if this.size < (n >>> Log2ConcatFaster) && again.isInstanceOf[Vector[_]] =>
var v = again.asInstanceOf[Vector[B]]
val ri = this.reverseIterator
while (ri.hasNext) v = ri.next +: v
@@ -241,8 +237,6 @@ override def companion: GenericCompanion[Vector] = Vector
else super.++(that.seq)
}
-
-
// semi-private api
private[immutable] def updateAt[B >: A](index: Int, elem: B): Vector[B] = {
@@ -251,11 +245,10 @@ override def companion: GenericCompanion[Vector] = Vector
s.initFrom(this)
s.dirty = dirty
s.gotoPosWritable(focus, idx, focus ^ idx) // if dirty commit changes; go to new pos and prepare for writing
- s.display0(idx & 0x1f) = elem.asInstanceOf[AnyRef]
+ s.display0(idx & 31) = elem.asInstanceOf[AnyRef]
s
}
-
private def gotoPosWritable(oldIndex: Int, newIndex: Int, xor: Int) = if (dirty) {
gotoPosWritable1(oldIndex, newIndex, xor)
} else {
@@ -270,7 +263,7 @@ override def companion: GenericCompanion[Vector] = Vector
dirty = true
}
- private[immutable] def appendFront[B>:A](value: B): Vector[B] = {
+ private[immutable] def appendFront[B >: A](value: B): Vector[B] = {
if (endIndex != startIndex) {
val blockIndex = (startIndex - 1) & ~31
val lo = (startIndex - 1) & 31
@@ -284,61 +277,46 @@ override def companion: GenericCompanion[Vector] = Vector
s
} else {
- val freeSpace = ((1<<5*(depth)) - endIndex) // free space at the right given the current tree-structure depth
- val shift = freeSpace & ~((1<<5*(depth-1))-1) // number of elements by which we'll shift right (only move at top level)
- val shiftBlocks = freeSpace >>> 5*(depth-1) // number of top-level blocks
+ val freeSpace = (1 << (5 * depth)) - endIndex // free space at the right given the current tree-structure depth
+ val shift = freeSpace & ~((1 << (5 * (depth - 1))) - 1) // number of elements by which we'll shift right (only move at top level)
+ val shiftBlocks = freeSpace >>> (5 * (depth - 1)) // number of top-level blocks
- //println("----- appendFront " + value + " at " + (startIndex - 1) + " reached block start")
if (shift != 0) {
// case A: we can shift right on the top level
- debug()
- //println("shifting right by " + shiftBlocks + " at level " + (depth-1) + " (had "+freeSpace+" free space)")
-
if (depth > 1) {
val newBlockIndex = blockIndex + shift
val newFocus = focus + shift
+
val s = new Vector(startIndex - 1 + shift, endIndex + shift, newBlockIndex)
s.initFrom(this)
s.dirty = dirty
s.shiftTopLevel(0, shiftBlocks) // shift right by n blocks
- s.debug()
s.gotoFreshPosWritable(newFocus, newBlockIndex, newFocus ^ newBlockIndex) // maybe create pos; prepare for writing
s.display0(lo) = value.asInstanceOf[AnyRef]
- //assert(depth == s.depth)
s
} else {
val newBlockIndex = blockIndex + 32
val newFocus = focus
- //assert(newBlockIndex == 0)
- //assert(newFocus == 0)
-
val s = new Vector(startIndex - 1 + shift, endIndex + shift, newBlockIndex)
s.initFrom(this)
s.dirty = dirty
s.shiftTopLevel(0, shiftBlocks) // shift right by n elements
s.gotoPosWritable(newFocus, newBlockIndex, newFocus ^ newBlockIndex) // prepare for writing
- s.display0(shift-1) = value.asInstanceOf[AnyRef]
- s.debug()
+ s.display0(shift - 1) = value.asInstanceOf[AnyRef]
s
}
} else if (blockIndex < 0) {
// case B: we need to move the whole structure
- val move = (1 << 5*(depth+1)) - (1 << 5*(depth))
- //println("moving right by " + move + " at level " + (depth-1) + " (had "+freeSpace+" free space)")
-
+ val move = (1 << (5 * (depth + 1))) - (1 << (5 * depth))
val newBlockIndex = blockIndex + move
val newFocus = focus + move
-
val s = new Vector(startIndex - 1 + move, endIndex + move, newBlockIndex)
s.initFrom(this)
s.dirty = dirty
- s.debug()
s.gotoFreshPosWritable(newFocus, newBlockIndex, newFocus ^ newBlockIndex) // could optimize: we know it will create a whole branch
s.display0(lo) = value.asInstanceOf[AnyRef]
- s.debug()
- //assert(s.depth == depth+1)
s
} else {
val newBlockIndex = blockIndex
@@ -349,31 +327,26 @@ override def companion: GenericCompanion[Vector] = Vector
s.dirty = dirty
s.gotoFreshPosWritable(newFocus, newBlockIndex, newFocus ^ newBlockIndex)
s.display0(lo) = value.asInstanceOf[AnyRef]
- //assert(s.depth == depth)
s
}
-
}
} else {
// empty vector, just insert single element at the back
val elems = new Array[AnyRef](32)
elems(31) = value.asInstanceOf[AnyRef]
- val s = new Vector(31,32,0)
+ val s = new Vector(31, 32, 0)
s.depth = 1
s.display0 = elems
s
}
}
- private[immutable] def appendBack[B>:A](value: B): Vector[B] = {
-// //println("------- append " + value)
-// debug()
+ private[immutable] def appendBack[B >: A](value: B): Vector[B] = {
if (endIndex != startIndex) {
val blockIndex = endIndex & ~31
val lo = endIndex & 31
if (endIndex != blockIndex) {
- //println("will make writable block (from "+focus+") at: " + blockIndex)
val s = new Vector(startIndex, endIndex + 1, blockIndex)
s.initFrom(this)
s.dirty = dirty
@@ -381,41 +354,31 @@ override def companion: GenericCompanion[Vector] = Vector
s.display0(lo) = value.asInstanceOf[AnyRef]
s
} else {
- val shift = startIndex & ~((1<<5*(depth-1))-1)
- val shiftBlocks = startIndex >>> 5*(depth-1)
-
- //println("----- appendBack " + value + " at " + endIndex + " reached block end")
+ val shift = startIndex & ~((1 << (5 * (depth - 1))) - 1)
+ val shiftBlocks = startIndex >>> (5 * (depth - 1))
if (shift != 0) {
- debug()
- //println("shifting left by " + shiftBlocks + " at level " + (depth-1) + " (had "+startIndex+" free space)")
if (depth > 1) {
val newBlockIndex = blockIndex - shift
val newFocus = focus - shift
+
val s = new Vector(startIndex - shift, endIndex + 1 - shift, newBlockIndex)
s.initFrom(this)
s.dirty = dirty
s.shiftTopLevel(shiftBlocks, 0) // shift left by n blocks
- s.debug()
s.gotoFreshPosWritable(newFocus, newBlockIndex, newFocus ^ newBlockIndex)
s.display0(lo) = value.asInstanceOf[AnyRef]
- s.debug()
- //assert(depth == s.depth)
s
} else {
val newBlockIndex = blockIndex - 32
val newFocus = focus
- //assert(newBlockIndex == 0)
- //assert(newFocus == 0)
-
val s = new Vector(startIndex - shift, endIndex + 1 - shift, newBlockIndex)
s.initFrom(this)
s.dirty = dirty
s.shiftTopLevel(shiftBlocks, 0) // shift right by n elements
s.gotoPosWritable(newFocus, newBlockIndex, newFocus ^ newBlockIndex)
s.display0(32 - shift) = value.asInstanceOf[AnyRef]
- s.debug()
s
}
} else {
@@ -427,18 +390,13 @@ override def companion: GenericCompanion[Vector] = Vector
s.dirty = dirty
s.gotoFreshPosWritable(newFocus, newBlockIndex, newFocus ^ newBlockIndex)
s.display0(lo) = value.asInstanceOf[AnyRef]
- //assert(s.depth == depth+1) might or might not create new level!
- if (s.depth == depth+1) {
- //println("creating new level " + s.depth + " (had "+0+" free space)")
- s.debug()
- }
s
}
}
} else {
val elems = new Array[AnyRef](32)
elems(0) = value.asInstanceOf[AnyRef]
- val s = new Vector(0,1,0)
+ val s = new Vector(0, 1, 0)
s.depth = 1
s.display0 = elems
s
@@ -449,39 +407,39 @@ override def companion: GenericCompanion[Vector] = Vector
// low-level implementation (needs cleanup, maybe move to util class)
private def shiftTopLevel(oldLeft: Int, newLeft: Int) = (depth - 1) match {
- case 0 =>
- display0 = copyRange(display0, oldLeft, newLeft)
- case 1 =>
- display1 = copyRange(display1, oldLeft, newLeft)
- case 2 =>
- display2 = copyRange(display2, oldLeft, newLeft)
- case 3 =>
- display3 = copyRange(display3, oldLeft, newLeft)
- case 4 =>
- display4 = copyRange(display4, oldLeft, newLeft)
- case 5 =>
- display5 = copyRange(display5, oldLeft, newLeft)
+ case 0 => display0 = copyRange(display0, oldLeft, newLeft)
+ case 1 => display1 = copyRange(display1, oldLeft, newLeft)
+ case 2 => display2 = copyRange(display2, oldLeft, newLeft)
+ case 3 => display3 = copyRange(display3, oldLeft, newLeft)
+ case 4 => display4 = copyRange(display4, oldLeft, newLeft)
+ case 5 => display5 = copyRange(display5, oldLeft, newLeft)
}
private def zeroLeft(array: Array[AnyRef], index: Int): Unit = {
- var i = 0; while (i < index) { array(i) = null; i+=1 }
+ var i = 0
+ while (i < index) {
+ array(i) = null
+ i += 1
+ }
}
private def zeroRight(array: Array[AnyRef], index: Int): Unit = {
- var i = index; while (i < array.length) { array(i) = null; i+=1 }
+ var i = index
+ while (i < array.length) {
+ array(i) = null
+ i += 1
+ }
}
private def copyLeft(array: Array[AnyRef], right: Int): Array[AnyRef] = {
-// if (array eq null)
-// println("OUCH!!! " + right + "/" + depth + "/"+startIndex + "/" + endIndex + "/" + focus)
- val a2 = new Array[AnyRef](array.length)
- Platform.arraycopy(array, 0, a2, 0, right)
- a2
+ val copy = new Array[AnyRef](array.length)
+ java.lang.System.arraycopy(array, 0, copy, 0, right)
+ copy
}
private def copyRight(array: Array[AnyRef], left: Int): Array[AnyRef] = {
- val a2 = new Array[AnyRef](array.length)
- Platform.arraycopy(array, left, a2, left, a2.length - left)
- a2
+ val copy = new Array[AnyRef](array.length)
+ java.lang.System.arraycopy(array, left, copy, left, copy.length - left)
+ copy
}
private def preClean(depth: Int) = {
@@ -513,38 +471,33 @@ override def companion: GenericCompanion[Vector] = Vector
// requires structure is at index cutIndex and writable at level 0
private def cleanLeftEdge(cutIndex: Int) = {
- if (cutIndex < (1 << 5)) {
+ if (cutIndex < (1 << 5)) {
zeroLeft(display0, cutIndex)
- } else
- if (cutIndex < (1 << 10)) {
- zeroLeft(display0, cutIndex & 0x1f)
- display1 = copyRight(display1, (cutIndex >>> 5))
- } else
- if (cutIndex < (1 << 15)) {
- zeroLeft(display0, cutIndex & 0x1f)
- display1 = copyRight(display1, (cutIndex >>> 5) & 0x1f)
- display2 = copyRight(display2, (cutIndex >>> 10))
- } else
- if (cutIndex < (1 << 20)) {
- zeroLeft(display0, cutIndex & 0x1f)
- display1 = copyRight(display1, (cutIndex >>> 5) & 0x1f)
- display2 = copyRight(display2, (cutIndex >>> 10) & 0x1f)
- display3 = copyRight(display3, (cutIndex >>> 15))
- } else
- if (cutIndex < (1 << 25)) {
- zeroLeft(display0, cutIndex & 0x1f)
- display1 = copyRight(display1, (cutIndex >>> 5) & 0x1f)
- display2 = copyRight(display2, (cutIndex >>> 10) & 0x1f)
- display3 = copyRight(display3, (cutIndex >>> 15) & 0x1f)
- display4 = copyRight(display4, (cutIndex >>> 20))
- } else
- if (cutIndex < (1 << 30)) {
- zeroLeft(display0, cutIndex & 0x1f)
- display1 = copyRight(display1, (cutIndex >>> 5) & 0x1f)
- display2 = copyRight(display2, (cutIndex >>> 10) & 0x1f)
- display3 = copyRight(display3, (cutIndex >>> 15) & 0x1f)
- display4 = copyRight(display4, (cutIndex >>> 20) & 0x1f)
- display5 = copyRight(display5, (cutIndex >>> 25))
+ } else if (cutIndex < (1 << 10)) {
+ zeroLeft(display0, cutIndex & 31)
+ display1 = copyRight(display1, cutIndex >>> 5)
+ } else if (cutIndex < (1 << 15)) {
+ zeroLeft(display0, cutIndex & 31)
+ display1 = copyRight(display1, (cutIndex >>> 5) & 31)
+ display2 = copyRight(display2, cutIndex >>> 10)
+ } else if (cutIndex < (1 << 20)) {
+ zeroLeft(display0, cutIndex & 31)
+ display1 = copyRight(display1, (cutIndex >>> 5) & 31)
+ display2 = copyRight(display2, (cutIndex >>> 10) & 31)
+ display3 = copyRight(display3, cutIndex >>> 15)
+ } else if (cutIndex < (1 << 25)) {
+ zeroLeft(display0, cutIndex & 31)
+ display1 = copyRight(display1, (cutIndex >>> 5) & 31)
+ display2 = copyRight(display2, (cutIndex >>> 10) & 31)
+ display3 = copyRight(display3, (cutIndex >>> 15) & 31)
+ display4 = copyRight(display4, cutIndex >>> 20)
+ } else if (cutIndex < (1 << 30)) {
+ zeroLeft(display0, cutIndex & 31)
+ display1 = copyRight(display1, (cutIndex >>> 5) & 31)
+ display2 = copyRight(display2, (cutIndex >>> 10) & 31)
+ display3 = copyRight(display3, (cutIndex >>> 15) & 31)
+ display4 = copyRight(display4, (cutIndex >>> 20) & 31)
+ display5 = copyRight(display5, cutIndex >>> 25)
} else {
throw new IllegalArgumentException()
}
@@ -552,49 +505,43 @@ override def companion: GenericCompanion[Vector] = Vector
// requires structure is writable and at index cutIndex
private def cleanRightEdge(cutIndex: Int) = {
-
// we're actually sitting one block left if cutIndex lies on a block boundary
// this means that we'll end up erasing the whole block!!
- if (cutIndex <= (1 << 5)) {
+ if (cutIndex <= (1 << 5)) {
zeroRight(display0, cutIndex)
- } else
- if (cutIndex <= (1 << 10)) {
- zeroRight(display0, ((cutIndex-1) & 0x1f) + 1)
- display1 = copyLeft(display1, (cutIndex >>> 5))
- } else
- if (cutIndex <= (1 << 15)) {
- zeroRight(display0, ((cutIndex-1) & 0x1f) + 1)
- display1 = copyLeft(display1, (((cutIndex-1) >>> 5) & 0x1f) + 1)
- display2 = copyLeft(display2, (cutIndex >>> 10))
- } else
- if (cutIndex <= (1 << 20)) {
- zeroRight(display0, ((cutIndex-1) & 0x1f) + 1)
- display1 = copyLeft(display1, (((cutIndex-1) >>> 5) & 0x1f) + 1)
- display2 = copyLeft(display2, (((cutIndex-1) >>> 10) & 0x1f) + 1)
- display3 = copyLeft(display3, (cutIndex >>> 15))
- } else
- if (cutIndex <= (1 << 25)) {
- zeroRight(display0, ((cutIndex-1) & 0x1f) + 1)
- display1 = copyLeft(display1, (((cutIndex-1) >>> 5) & 0x1f) + 1)
- display2 = copyLeft(display2, (((cutIndex-1) >>> 10) & 0x1f) + 1)
- display3 = copyLeft(display3, (((cutIndex-1) >>> 15) & 0x1f) + 1)
- display4 = copyLeft(display4, (cutIndex >>> 20))
- } else
- if (cutIndex <= (1 << 30)) {
- zeroRight(display0, ((cutIndex-1) & 0x1f) + 1)
- display1 = copyLeft(display1, (((cutIndex-1) >>> 5) & 0x1f) + 1)
- display2 = copyLeft(display2, (((cutIndex-1) >>> 10) & 0x1f) + 1)
- display3 = copyLeft(display3, (((cutIndex-1) >>> 15) & 0x1f) + 1)
- display4 = copyLeft(display4, (((cutIndex-1) >>> 20) & 0x1f) + 1)
- display5 = copyLeft(display5, (cutIndex >>> 25))
+ } else if (cutIndex <= (1 << 10)) {
+ zeroRight(display0, ((cutIndex - 1) & 31) + 1)
+ display1 = copyLeft(display1, cutIndex >>> 5)
+ } else if (cutIndex <= (1 << 15)) {
+ zeroRight(display0, ((cutIndex - 1) & 31) + 1)
+ display1 = copyLeft(display1, (((cutIndex - 1) >>> 5) & 31) + 1)
+ display2 = copyLeft(display2, cutIndex >>> 10)
+ } else if (cutIndex <= (1 << 20)) {
+ zeroRight(display0, ((cutIndex - 1) & 31) + 1)
+ display1 = copyLeft(display1, (((cutIndex - 1) >>> 5) & 31) + 1)
+ display2 = copyLeft(display2, (((cutIndex - 1) >>> 10) & 31) + 1)
+ display3 = copyLeft(display3, cutIndex >>> 15)
+ } else if (cutIndex <= (1 << 25)) {
+ zeroRight(display0, ((cutIndex - 1) & 31) + 1)
+ display1 = copyLeft(display1, (((cutIndex - 1) >>> 5) & 31) + 1)
+ display2 = copyLeft(display2, (((cutIndex - 1) >>> 10) & 31) + 1)
+ display3 = copyLeft(display3, (((cutIndex - 1) >>> 15) & 31) + 1)
+ display4 = copyLeft(display4, cutIndex >>> 20)
+ } else if (cutIndex <= (1 << 30)) {
+ zeroRight(display0, ((cutIndex - 1) & 31) + 1)
+ display1 = copyLeft(display1, (((cutIndex - 1) >>> 5) & 31) + 1)
+ display2 = copyLeft(display2, (((cutIndex - 1) >>> 10) & 31) + 1)
+ display3 = copyLeft(display3, (((cutIndex - 1) >>> 15) & 31) + 1)
+ display4 = copyLeft(display4, (((cutIndex - 1) >>> 20) & 31) + 1)
+ display5 = copyLeft(display5, cutIndex >>> 25)
} else {
throw new IllegalArgumentException()
}
}
private def requiredDepth(xor: Int) = {
- if (xor < (1 << 5)) 1
+ if (xor < (1 << 5)) 1
else if (xor < (1 << 10)) 2
else if (xor < (1 << 15)) 3
else if (xor < (1 << 20)) 4
@@ -607,24 +554,11 @@ override def companion: GenericCompanion[Vector] = Vector
val blockIndex = cutIndex & ~31
val xor = cutIndex ^ (endIndex - 1)
val d = requiredDepth(xor)
- val shift = (cutIndex & ~((1 << (5*d))-1))
-
- //println("cut front at " + cutIndex + ".." + endIndex + " (xor: "+xor+" shift: " + shift + " d: " + d +")")
-
-/*
- val s = new Vector(cutIndex-shift, endIndex-shift, blockIndex-shift)
- s.initFrom(this)
- if (s.depth > 1)
- s.gotoPos(blockIndex, focus ^ blockIndex)
- s.depth = d
- s.stabilize(blockIndex-shift)
- s.cleanLeftEdge(cutIndex-shift)
- s
-*/
+ val shift = cutIndex & ~((1 << (5 * d)) - 1)
// need to init with full display iff going to cutIndex requires swapping block at level >= d
- val s = new Vector(cutIndex-shift, endIndex-shift, blockIndex-shift)
+ val s = new Vector(cutIndex - shift, endIndex - shift, blockIndex - shift)
s.initFrom(this)
s.dirty = dirty
s.gotoPosWritable(focus, blockIndex, focus ^ blockIndex)
@@ -637,25 +571,18 @@ override def companion: GenericCompanion[Vector] = Vector
val blockIndex = (cutIndex - 1) & ~31
val xor = startIndex ^ (cutIndex - 1)
val d = requiredDepth(xor)
- val shift = (startIndex & ~((1 << (5*d))-1))
-
-/*
- println("cut back at " + startIndex + ".." + cutIndex + " (xor: "+xor+" d: " + d +")")
- if (cutIndex == blockIndex + 32)
- println("OUCH!!!")
-*/
- val s = new Vector(startIndex-shift, cutIndex-shift, blockIndex-shift)
+ val shift = startIndex & ~((1 << (5 * d)) - 1)
+
+ val s = new Vector(startIndex - shift, cutIndex - shift, blockIndex - shift)
s.initFrom(this)
s.dirty = dirty
s.gotoPosWritable(focus, blockIndex, focus ^ blockIndex)
s.preClean(d)
- s.cleanRightEdge(cutIndex-shift)
+ s.cleanRightEdge(cutIndex - shift)
s
}
-
}
-
class VectorIterator[+A](_startIndex: Int, endIndex: Int)
extends AbstractIterator[A]
with Iterator[A]
@@ -678,7 +605,7 @@ extends AbstractIterator[A]
if (lo == endLo) {
if (blockIndex + lo < endIndex) {
- val newBlockIndex = blockIndex+32
+ val newBlockIndex = blockIndex + 32
gotoNextBlockStart(newBlockIndex, blockIndex ^ newBlockIndex)
blockIndex = newBlockIndex
@@ -704,8 +631,8 @@ extends AbstractIterator[A]
}
}
-
-final class VectorBuilder[A]() extends Builder[A,Vector[A]] with VectorPointer[A @uncheckedVariance] {
+/** A class to build instances of `Vector`. This builder is reusable. */
+final class VectorBuilder[A]() extends ReusableBuilder[A, Vector[A]] with VectorPointer[A @uncheckedVariance] {
// possible alternative: start with display0 = null, blockIndex = -32, lo = 32
// to avoid allocating initial array if the result will be empty anyways
@@ -716,9 +643,9 @@ final class VectorBuilder[A]() extends Builder[A,Vector[A]] with VectorPointer[A
private var blockIndex = 0
private var lo = 0
- def += (elem: A): this.type = {
+ def +=(elem: A): this.type = {
if (lo >= display0.length) {
- val newBlockIndex = blockIndex+32
+ val newBlockIndex = blockIndex + 32
gotoNextBlockStartWritable(newBlockIndex, blockIndex ^ newBlockIndex)
blockIndex = newBlockIndex
lo = 0
@@ -728,8 +655,7 @@ final class VectorBuilder[A]() extends Builder[A,Vector[A]] with VectorPointer[A
this
}
- override def ++=(xs: TraversableOnce[A]): this.type =
- super.++=(xs)
+ override def ++=(xs: TraversableOnce[A]): this.type = super.++=(xs)
def result: Vector[A] = {
val size = blockIndex + lo
@@ -749,10 +675,8 @@ final class VectorBuilder[A]() extends Builder[A,Vector[A]] with VectorPointer[A
}
}
-
-
private[immutable] trait VectorPointer[T] {
- private[immutable] var depth: Int = _
+ private[immutable] var depth: Int = _
private[immutable] var display0: Array[AnyRef] = _
private[immutable] var display1: Array[AnyRef] = _
private[immutable] var display2: Array[AnyRef] = _
@@ -797,98 +721,102 @@ private[immutable] trait VectorPointer[T] {
}
}
-
// requires structure is at pos oldIndex = xor ^ index
private[immutable] final def getElem(index: Int, xor: Int): T = {
- if (xor < (1 << 5)) { // level = 0
- display0(index & 31).asInstanceOf[T]
- } else
- if (xor < (1 << 10)) { // level = 1
- display1((index >> 5) & 31).asInstanceOf[Array[AnyRef]](index & 31).asInstanceOf[T]
- } else
- if (xor < (1 << 15)) { // level = 2
- display2((index >> 10) & 31).asInstanceOf[Array[AnyRef]]((index >> 5) & 31).asInstanceOf[Array[AnyRef]](index & 31).asInstanceOf[T]
- } else
- if (xor < (1 << 20)) { // level = 3
- display3((index >> 15) & 31).asInstanceOf[Array[AnyRef]]((index >> 10) & 31).asInstanceOf[Array[AnyRef]]((index >> 5) & 31).asInstanceOf[Array[AnyRef]](index & 31).asInstanceOf[T]
- } else
- if (xor < (1 << 25)) { // level = 4
- display4((index >> 20) & 31).asInstanceOf[Array[AnyRef]]((index >> 15) & 31).asInstanceOf[Array[AnyRef]]((index >> 10) & 31).asInstanceOf[Array[AnyRef]]((index >> 5) & 31).asInstanceOf[Array[AnyRef]](index & 31).asInstanceOf[T]
- } else
- if (xor < (1 << 30)) { // level = 5
- display5((index >> 25) & 31).asInstanceOf[Array[AnyRef]]((index >> 20) & 31).asInstanceOf[Array[AnyRef]]((index >> 15) & 31).asInstanceOf[Array[AnyRef]]((index >> 10) & 31).asInstanceOf[Array[AnyRef]]((index >> 5) & 31).asInstanceOf[Array[AnyRef]](index & 31).asInstanceOf[T]
- } else { // level = 6
+ if (xor < (1 << 5)) { // level = 0
+ (display0
+ (index & 31).asInstanceOf[T])
+ } else if (xor < (1 << 10)) { // level = 1
+ (display1
+ ((index >>> 5) & 31).asInstanceOf[Array[AnyRef]]
+ (index & 31).asInstanceOf[T])
+ } else if (xor < (1 << 15)) { // level = 2
+ (display2
+ ((index >>> 10) & 31).asInstanceOf[Array[AnyRef]]
+ ((index >>> 5) & 31).asInstanceOf[Array[AnyRef]]
+ (index & 31).asInstanceOf[T])
+ } else if (xor < (1 << 20)) { // level = 3
+ (display3
+ ((index >>> 15) & 31).asInstanceOf[Array[AnyRef]]
+ ((index >>> 10) & 31).asInstanceOf[Array[AnyRef]]
+ ((index >>> 5) & 31).asInstanceOf[Array[AnyRef]]
+ (index & 31).asInstanceOf[T])
+ } else if (xor < (1 << 25)) { // level = 4
+ (display4
+ ((index >>> 20) & 31).asInstanceOf[Array[AnyRef]]
+ ((index >>> 15) & 31).asInstanceOf[Array[AnyRef]]
+ ((index >>> 10) & 31).asInstanceOf[Array[AnyRef]]
+ ((index >>> 5) & 31).asInstanceOf[Array[AnyRef]]
+ (index & 31).asInstanceOf[T])
+ } else if (xor < (1 << 30)) { // level = 5
+ (display5
+ ((index >>> 25) & 31).asInstanceOf[Array[AnyRef]]
+ ((index >>> 20) & 31).asInstanceOf[Array[AnyRef]]
+ ((index >>> 15) & 31).asInstanceOf[Array[AnyRef]]
+ ((index >>> 10) & 31).asInstanceOf[Array[AnyRef]]
+ ((index >>> 5) & 31).asInstanceOf[Array[AnyRef]]
+ (index & 31).asInstanceOf[T])
+ } else { // level = 6
throw new IllegalArgumentException()
}
}
-
// go to specific position
// requires structure is at pos oldIndex = xor ^ index,
// ensures structure is at pos index
private[immutable] final def gotoPos(index: Int, xor: Int): Unit = {
- if (xor < (1 << 5)) { // level = 0 (could maybe removed)
- } else
- if (xor < (1 << 10)) { // level = 1
- display0 = display1((index >> 5) & 31).asInstanceOf[Array[AnyRef]]
- } else
- if (xor < (1 << 15)) { // level = 2
- display1 = display2((index >> 10) & 31).asInstanceOf[Array[AnyRef]]
- display0 = display1((index >> 5) & 31).asInstanceOf[Array[AnyRef]]
- } else
- if (xor < (1 << 20)) { // level = 3
- display2 = display3((index >> 15) & 31).asInstanceOf[Array[AnyRef]]
- display1 = display2((index >> 10) & 31).asInstanceOf[Array[AnyRef]]
- display0 = display1((index >> 5) & 31).asInstanceOf[Array[AnyRef]]
- } else
- if (xor < (1 << 25)) { // level = 4
- display3 = display4((index >> 20) & 31).asInstanceOf[Array[AnyRef]]
- display2 = display3((index >> 15) & 31).asInstanceOf[Array[AnyRef]]
- display1 = display2((index >> 10) & 31).asInstanceOf[Array[AnyRef]]
- display0 = display1((index >> 5) & 31).asInstanceOf[Array[AnyRef]]
- } else
- if (xor < (1 << 30)) { // level = 5
- display4 = display5((index >> 25) & 31).asInstanceOf[Array[AnyRef]]
- display3 = display4((index >> 20) & 31).asInstanceOf[Array[AnyRef]]
- display2 = display3((index >> 15) & 31).asInstanceOf[Array[AnyRef]]
- display1 = display2((index >> 10) & 31).asInstanceOf[Array[AnyRef]]
- display0 = display1((index >> 5) & 31).asInstanceOf[Array[AnyRef]]
- } else { // level = 6
+ if (xor < (1 << 5)) { // level = 0
+ // we're already at the block start pos
+ } else if (xor < (1 << 10)) { // level = 1
+ display0 = display1((index >>> 5) & 31).asInstanceOf[Array[AnyRef]]
+ } else if (xor < (1 << 15)) { // level = 2
+ display1 = display2((index >>> 10) & 31).asInstanceOf[Array[AnyRef]]
+ display0 = display1((index >>> 5) & 31).asInstanceOf[Array[AnyRef]]
+ } else if (xor < (1 << 20)) { // level = 3
+ display2 = display3((index >>> 15) & 31).asInstanceOf[Array[AnyRef]]
+ display1 = display2((index >>> 10) & 31).asInstanceOf[Array[AnyRef]]
+ display0 = display1((index >>> 5) & 31).asInstanceOf[Array[AnyRef]]
+ } else if (xor < (1 << 25)) { // level = 4
+ display3 = display4((index >>> 20) & 31).asInstanceOf[Array[AnyRef]]
+ display2 = display3((index >>> 15) & 31).asInstanceOf[Array[AnyRef]]
+ display1 = display2((index >>> 10) & 31).asInstanceOf[Array[AnyRef]]
+ display0 = display1((index >>> 5) & 31).asInstanceOf[Array[AnyRef]]
+ } else if (xor < (1 << 30)) { // level = 5
+ display4 = display5((index >>> 25) & 31).asInstanceOf[Array[AnyRef]]
+ display3 = display4((index >>> 20) & 31).asInstanceOf[Array[AnyRef]]
+ display2 = display3((index >>> 15) & 31).asInstanceOf[Array[AnyRef]]
+ display1 = display2((index >>> 10) & 31).asInstanceOf[Array[AnyRef]]
+ display0 = display1((index >>> 5) & 31).asInstanceOf[Array[AnyRef]]
+ } else { // level = 6
throw new IllegalArgumentException()
}
}
-
-
// USED BY ITERATOR
// xor: oldIndex ^ index
private[immutable] final def gotoNextBlockStart(index: Int, xor: Int): Unit = { // goto block start pos
- if (xor < (1 << 10)) { // level = 1
- display0 = display1((index >> 5) & 31).asInstanceOf[Array[AnyRef]]
- } else
- if (xor < (1 << 15)) { // level = 2
- display1 = display2((index >> 10) & 31).asInstanceOf[Array[AnyRef]]
+ if (xor < (1 << 10)) { // level = 1
+ display0 = display1((index >>> 5) & 31).asInstanceOf[Array[AnyRef]]
+ } else if (xor < (1 << 15)) { // level = 2
+ display1 = display2((index >>> 10) & 31).asInstanceOf[Array[AnyRef]]
display0 = display1(0).asInstanceOf[Array[AnyRef]]
- } else
- if (xor < (1 << 20)) { // level = 3
- display2 = display3((index >> 15) & 31).asInstanceOf[Array[AnyRef]]
+ } else if (xor < (1 << 20)) { // level = 3
+ display2 = display3((index >>> 15) & 31).asInstanceOf[Array[AnyRef]]
display1 = display2(0).asInstanceOf[Array[AnyRef]]
display0 = display1(0).asInstanceOf[Array[AnyRef]]
- } else
- if (xor < (1 << 25)) { // level = 4
- display3 = display4((index >> 20) & 31).asInstanceOf[Array[AnyRef]]
+ } else if (xor < (1 << 25)) { // level = 4
+ display3 = display4((index >>> 20) & 31).asInstanceOf[Array[AnyRef]]
display2 = display3(0).asInstanceOf[Array[AnyRef]]
display1 = display2(0).asInstanceOf[Array[AnyRef]]
display0 = display1(0).asInstanceOf[Array[AnyRef]]
- } else
- if (xor < (1 << 30)) { // level = 5
- display4 = display5((index >> 25) & 31).asInstanceOf[Array[AnyRef]]
+ } else if (xor < (1 << 30)) { // level = 5
+ display4 = display5((index >>> 25) & 31).asInstanceOf[Array[AnyRef]]
display3 = display4(0).asInstanceOf[Array[AnyRef]]
display2 = display3(0).asInstanceOf[Array[AnyRef]]
display1 = display2(0).asInstanceOf[Array[AnyRef]]
display0 = display1(0).asInstanceOf[Array[AnyRef]]
- } else { // level = 6
+ } else { // level = 6
throw new IllegalArgumentException()
}
}
@@ -897,73 +825,65 @@ private[immutable] trait VectorPointer[T] {
// xor: oldIndex ^ index
private[immutable] final def gotoNextBlockStartWritable(index: Int, xor: Int): Unit = { // goto block start pos
- if (xor < (1 << 10)) { // level = 1
- if (depth == 1) { display1 = new Array(32); display1(0) = display0; depth+=1}
+ if (xor < (1 << 10)) { // level = 1
+ if (depth == 1) { display1 = new Array(32); display1(0) = display0; depth += 1 }
display0 = new Array(32)
- display1((index >> 5) & 31) = display0
- } else
- if (xor < (1 << 15)) { // level = 2
- if (depth == 2) { display2 = new Array(32); display2(0) = display1; depth+=1}
+ display1((index >>> 5) & 31) = display0
+ } else if (xor < (1 << 15)) { // level = 2
+ if (depth == 2) { display2 = new Array(32); display2(0) = display1; depth += 1 }
display0 = new Array(32)
display1 = new Array(32)
- display1((index >> 5) & 31) = display0
- display2((index >> 10) & 31) = display1
- } else
- if (xor < (1 << 20)) { // level = 3
- if (depth == 3) { display3 = new Array(32); display3(0) = display2; depth+=1}
+ display1((index >>> 5) & 31) = display0
+ display2((index >>> 10) & 31) = display1
+ } else if (xor < (1 << 20)) { // level = 3
+ if (depth == 3) { display3 = new Array(32); display3(0) = display2; depth += 1 }
display0 = new Array(32)
display1 = new Array(32)
display2 = new Array(32)
- display1((index >> 5) & 31) = display0
- display2((index >> 10) & 31) = display1
- display3((index >> 15) & 31) = display2
- } else
- if (xor < (1 << 25)) { // level = 4
- if (depth == 4) { display4 = new Array(32); display4(0) = display3; depth+=1}
+ display1((index >>> 5) & 31) = display0
+ display2((index >>> 10) & 31) = display1
+ display3((index >>> 15) & 31) = display2
+ } else if (xor < (1 << 25)) { // level = 4
+ if (depth == 4) { display4 = new Array(32); display4(0) = display3; depth += 1 }
display0 = new Array(32)
display1 = new Array(32)
display2 = new Array(32)
display3 = new Array(32)
- display1((index >> 5) & 31) = display0
- display2((index >> 10) & 31) = display1
- display3((index >> 15) & 31) = display2
- display4((index >> 20) & 31) = display3
- } else
- if (xor < (1 << 30)) { // level = 5
- if (depth == 5) { display5 = new Array(32); display5(0) = display4; depth+=1}
+ display1((index >>> 5) & 31) = display0
+ display2((index >>> 10) & 31) = display1
+ display3((index >>> 15) & 31) = display2
+ display4((index >>> 20) & 31) = display3
+ } else if (xor < (1 << 30)) { // level = 5
+ if (depth == 5) { display5 = new Array(32); display5(0) = display4; depth += 1 }
display0 = new Array(32)
display1 = new Array(32)
display2 = new Array(32)
display3 = new Array(32)
display4 = new Array(32)
- display1((index >> 5) & 31) = display0
- display2((index >> 10) & 31) = display1
- display3((index >> 15) & 31) = display2
- display4((index >> 20) & 31) = display3
- display5((index >> 25) & 31) = display4
- } else { // level = 6
+ display1((index >>> 5) & 31) = display0
+ display2((index >>> 10) & 31) = display1
+ display3((index >>> 15) & 31) = display2
+ display4((index >>> 20) & 31) = display3
+ display5((index >>> 25) & 31) = display4
+ } else { // level = 6
throw new IllegalArgumentException()
}
}
-
-
// STUFF BELOW USED BY APPEND / UPDATE
- private[immutable] final def copyOf(a: Array[AnyRef]) = {
- val b = new Array[AnyRef](a.length)
- Platform.arraycopy(a, 0, b, 0, a.length)
- b
+ private[immutable] final def copyOf(a: Array[AnyRef]): Array[AnyRef] = {
+ val copy = new Array[AnyRef](a.length)
+ java.lang.System.arraycopy(a, 0, copy, 0, a.length)
+ copy
}
- private[immutable] final def nullSlotAndCopy(array: Array[AnyRef], index: Int) = {
- //println("copy and null")
+ private[immutable] final def nullSlotAndCopy(array: Array[AnyRef], index: Int): Array[AnyRef] = {
val x = array(index)
array(index) = null
copyOf(x.asInstanceOf[Array[AnyRef]])
}
-
// make sure there is no aliasing
// requires structure is at pos index
// ensures structure is clean and at pos index and writable at all levels except 0
@@ -975,40 +895,39 @@ private[immutable] trait VectorPointer[T] {
display3 = copyOf(display3)
display2 = copyOf(display2)
display1 = copyOf(display1)
- display5((index >> 25) & 31) = display4
- display4((index >> 20) & 31) = display3
- display3((index >> 15) & 31) = display2
- display2((index >> 10) & 31) = display1
- display1((index >> 5) & 31) = display0
+ display5((index >>> 25) & 31) = display4
+ display4((index >>> 20) & 31) = display3
+ display3((index >>> 15) & 31) = display2
+ display2((index >>> 10) & 31) = display1
+ display1((index >>> 5) & 31) = display0
case 4 =>
display4 = copyOf(display4)
display3 = copyOf(display3)
display2 = copyOf(display2)
display1 = copyOf(display1)
- display4((index >> 20) & 31) = display3
- display3((index >> 15) & 31) = display2
- display2((index >> 10) & 31) = display1
- display1((index >> 5) & 31) = display0
+ display4((index >>> 20) & 31) = display3
+ display3((index >>> 15) & 31) = display2
+ display2((index >>> 10) & 31) = display1
+ display1((index >>> 5) & 31) = display0
case 3 =>
display3 = copyOf(display3)
display2 = copyOf(display2)
display1 = copyOf(display1)
- display3((index >> 15) & 31) = display2
- display2((index >> 10) & 31) = display1
- display1((index >> 5) & 31) = display0
+ display3((index >>> 15) & 31) = display2
+ display2((index >>> 10) & 31) = display1
+ display1((index >>> 5) & 31) = display0
case 2 =>
display2 = copyOf(display2)
display1 = copyOf(display1)
- display2((index >> 10) & 31) = display1
- display1((index >> 5) & 31) = display0
+ display2((index >>> 10) & 31) = display1
+ display1((index >>> 5) & 31) = display0
case 1 =>
display1 = copyOf(display1)
- display1((index >> 5) & 31) = display0
+ display1((index >>> 5) & 31) = display0
case 0 =>
}
-
/// USED IN UPDATE AND APPEND BACK
// prepare for writing at an existing position
@@ -1018,29 +937,29 @@ private[immutable] trait VectorPointer[T] {
private[immutable] final def gotoPosWritable0(newIndex: Int, xor: Int): Unit = (depth - 1) match {
case 5 =>
display5 = copyOf(display5)
- display4 = nullSlotAndCopy(display5, (newIndex >> 25) & 31).asInstanceOf[Array[AnyRef]]
- display3 = nullSlotAndCopy(display4, (newIndex >> 20) & 31).asInstanceOf[Array[AnyRef]]
- display2 = nullSlotAndCopy(display3, (newIndex >> 15) & 31).asInstanceOf[Array[AnyRef]]
- display1 = nullSlotAndCopy(display2, (newIndex >> 10) & 31).asInstanceOf[Array[AnyRef]]
- display0 = nullSlotAndCopy(display1, (newIndex >> 5) & 31).asInstanceOf[Array[AnyRef]]
+ display4 = nullSlotAndCopy(display5, (newIndex >>> 25) & 31)
+ display3 = nullSlotAndCopy(display4, (newIndex >>> 20) & 31)
+ display2 = nullSlotAndCopy(display3, (newIndex >>> 15) & 31)
+ display1 = nullSlotAndCopy(display2, (newIndex >>> 10) & 31)
+ display0 = nullSlotAndCopy(display1, (newIndex >>> 5) & 31)
case 4 =>
display4 = copyOf(display4)
- display3 = nullSlotAndCopy(display4, (newIndex >> 20) & 31).asInstanceOf[Array[AnyRef]]
- display2 = nullSlotAndCopy(display3, (newIndex >> 15) & 31).asInstanceOf[Array[AnyRef]]
- display1 = nullSlotAndCopy(display2, (newIndex >> 10) & 31).asInstanceOf[Array[AnyRef]]
- display0 = nullSlotAndCopy(display1, (newIndex >> 5) & 31).asInstanceOf[Array[AnyRef]]
+ display3 = nullSlotAndCopy(display4, (newIndex >>> 20) & 31)
+ display2 = nullSlotAndCopy(display3, (newIndex >>> 15) & 31)
+ display1 = nullSlotAndCopy(display2, (newIndex >>> 10) & 31)
+ display0 = nullSlotAndCopy(display1, (newIndex >>> 5) & 31)
case 3 =>
display3 = copyOf(display3)
- display2 = nullSlotAndCopy(display3, (newIndex >> 15) & 31).asInstanceOf[Array[AnyRef]]
- display1 = nullSlotAndCopy(display2, (newIndex >> 10) & 31).asInstanceOf[Array[AnyRef]]
- display0 = nullSlotAndCopy(display1, (newIndex >> 5) & 31).asInstanceOf[Array[AnyRef]]
+ display2 = nullSlotAndCopy(display3, (newIndex >>> 15) & 31)
+ display1 = nullSlotAndCopy(display2, (newIndex >>> 10) & 31)
+ display0 = nullSlotAndCopy(display1, (newIndex >>> 5) & 31)
case 2 =>
display2 = copyOf(display2)
- display1 = nullSlotAndCopy(display2, (newIndex >> 10) & 31).asInstanceOf[Array[AnyRef]]
- display0 = nullSlotAndCopy(display1, (newIndex >> 5) & 31).asInstanceOf[Array[AnyRef]]
+ display1 = nullSlotAndCopy(display2, (newIndex >>> 10) & 31)
+ display0 = nullSlotAndCopy(display1, (newIndex >>> 5) & 31)
case 1 =>
display1 = copyOf(display1)
- display0 = nullSlotAndCopy(display1, (newIndex >> 5) & 31).asInstanceOf[Array[AnyRef]]
+ display0 = nullSlotAndCopy(display1, (newIndex >>> 5) & 31)
case 0 =>
display0 = copyOf(display0)
}
@@ -1049,64 +968,59 @@ private[immutable] trait VectorPointer[T] {
// requires structure is dirty and at pos oldIndex,
// ensures structure is dirty and at pos newIndex and writable at level 0
private[immutable] final def gotoPosWritable1(oldIndex: Int, newIndex: Int, xor: Int): Unit = {
- if (xor < (1 << 5)) { // level = 0
+ if (xor < (1 << 5)) { // level = 0
display0 = copyOf(display0)
- } else
- if (xor < (1 << 10)) { // level = 1
+ } else if (xor < (1 << 10)) { // level = 1
display1 = copyOf(display1)
- display1((oldIndex >> 5) & 31) = display0
- display0 = nullSlotAndCopy(display1, (newIndex >> 5) & 31)
- } else
- if (xor < (1 << 15)) { // level = 2
+ display1((oldIndex >>> 5) & 31) = display0
+ display0 = nullSlotAndCopy(display1, (newIndex >>> 5) & 31)
+ } else if (xor < (1 << 15)) { // level = 2
display1 = copyOf(display1)
display2 = copyOf(display2)
- display1((oldIndex >> 5) & 31) = display0
- display2((oldIndex >> 10) & 31) = display1
- display1 = nullSlotAndCopy(display2, (newIndex >> 10) & 31).asInstanceOf[Array[AnyRef]]
- display0 = nullSlotAndCopy(display1, (newIndex >> 5) & 31).asInstanceOf[Array[AnyRef]]
- } else
- if (xor < (1 << 20)) { // level = 3
+ display1((oldIndex >>> 5) & 31) = display0
+ display2((oldIndex >>> 10) & 31) = display1
+ display1 = nullSlotAndCopy(display2, (newIndex >>> 10) & 31)
+ display0 = nullSlotAndCopy(display1, (newIndex >>> 5) & 31)
+ } else if (xor < (1 << 20)) { // level = 3
display1 = copyOf(display1)
display2 = copyOf(display2)
display3 = copyOf(display3)
- display1((oldIndex >> 5) & 31) = display0
- display2((oldIndex >> 10) & 31) = display1
- display3((oldIndex >> 15) & 31) = display2
- display2 = nullSlotAndCopy(display3, (newIndex >> 15) & 31).asInstanceOf[Array[AnyRef]]
- display1 = nullSlotAndCopy(display2, (newIndex >> 10) & 31).asInstanceOf[Array[AnyRef]]
- display0 = nullSlotAndCopy(display1, (newIndex >> 5) & 31).asInstanceOf[Array[AnyRef]]
- } else
- if (xor < (1 << 25)) { // level = 4
+ display1((oldIndex >>> 5) & 31) = display0
+ display2((oldIndex >>> 10) & 31) = display1
+ display3((oldIndex >>> 15) & 31) = display2
+ display2 = nullSlotAndCopy(display3, (newIndex >>> 15) & 31)
+ display1 = nullSlotAndCopy(display2, (newIndex >>> 10) & 31)
+ display0 = nullSlotAndCopy(display1, (newIndex >>> 5) & 31)
+ } else if (xor < (1 << 25)) { // level = 4
display1 = copyOf(display1)
display2 = copyOf(display2)
display3 = copyOf(display3)
display4 = copyOf(display4)
- display1((oldIndex >> 5) & 31) = display0
- display2((oldIndex >> 10) & 31) = display1
- display3((oldIndex >> 15) & 31) = display2
- display4((oldIndex >> 20) & 31) = display3
- display3 = nullSlotAndCopy(display4, (newIndex >> 20) & 31).asInstanceOf[Array[AnyRef]]
- display2 = nullSlotAndCopy(display3, (newIndex >> 15) & 31).asInstanceOf[Array[AnyRef]]
- display1 = nullSlotAndCopy(display2, (newIndex >> 10) & 31).asInstanceOf[Array[AnyRef]]
- display0 = nullSlotAndCopy(display1, (newIndex >> 5) & 31).asInstanceOf[Array[AnyRef]]
- } else
- if (xor < (1 << 30)) { // level = 5
+ display1((oldIndex >>> 5) & 31) = display0
+ display2((oldIndex >>> 10) & 31) = display1
+ display3((oldIndex >>> 15) & 31) = display2
+ display4((oldIndex >>> 20) & 31) = display3
+ display3 = nullSlotAndCopy(display4, (newIndex >>> 20) & 31)
+ display2 = nullSlotAndCopy(display3, (newIndex >>> 15) & 31)
+ display1 = nullSlotAndCopy(display2, (newIndex >>> 10) & 31)
+ display0 = nullSlotAndCopy(display1, (newIndex >>> 5) & 31)
+ } else if (xor < (1 << 30)) { // level = 5
display1 = copyOf(display1)
display2 = copyOf(display2)
display3 = copyOf(display3)
display4 = copyOf(display4)
display5 = copyOf(display5)
- display1((oldIndex >> 5) & 31) = display0
- display2((oldIndex >> 10) & 31) = display1
- display3((oldIndex >> 15) & 31) = display2
- display4((oldIndex >> 20) & 31) = display3
- display5((oldIndex >> 25) & 31) = display4
- display4 = nullSlotAndCopy(display5, (newIndex >> 25) & 31).asInstanceOf[Array[AnyRef]]
- display3 = nullSlotAndCopy(display4, (newIndex >> 20) & 31).asInstanceOf[Array[AnyRef]]
- display2 = nullSlotAndCopy(display3, (newIndex >> 15) & 31).asInstanceOf[Array[AnyRef]]
- display1 = nullSlotAndCopy(display2, (newIndex >> 10) & 31).asInstanceOf[Array[AnyRef]]
- display0 = nullSlotAndCopy(display1, (newIndex >> 5) & 31).asInstanceOf[Array[AnyRef]]
- } else { // level = 6
+ display1((oldIndex >>> 5) & 31) = display0
+ display2((oldIndex >>> 10) & 31) = display1
+ display3((oldIndex >>> 15) & 31) = display2
+ display4((oldIndex >>> 20) & 31) = display3
+ display5((oldIndex >>> 25) & 31) = display4
+ display4 = nullSlotAndCopy(display5, (newIndex >>> 25) & 31)
+ display3 = nullSlotAndCopy(display4, (newIndex >>> 20) & 31)
+ display2 = nullSlotAndCopy(display3, (newIndex >>> 15) & 31)
+ display1 = nullSlotAndCopy(display2, (newIndex >>> 10) & 31)
+ display0 = nullSlotAndCopy(display1, (newIndex >>> 5) & 31)
+ } else { // level = 6
throw new IllegalArgumentException()
}
}
@@ -1116,117 +1030,83 @@ private[immutable] trait VectorPointer[T] {
private[immutable] final def copyRange(array: Array[AnyRef], oldLeft: Int, newLeft: Int) = {
val elems = new Array[AnyRef](32)
- Platform.arraycopy(array, oldLeft, elems, newLeft, 32 - math.max(newLeft,oldLeft))
+ java.lang.System.arraycopy(array, oldLeft, elems, newLeft, 32 - math.max(newLeft, oldLeft))
elems
}
-
-
// USED IN APPEND
// create a new block at the bottom level (and possibly nodes on its path) and prepares for writing
// requires structure is clean and at pos oldIndex,
// ensures structure is dirty and at pos newIndex and writable at level 0
private[immutable] final def gotoFreshPosWritable0(oldIndex: Int, newIndex: Int, xor: Int): Unit = { // goto block start pos
- if (xor < (1 << 5)) { // level = 0
- //println("XXX clean with low xor")
- } else
- if (xor < (1 << 10)) { // level = 1
+ if (xor < (1 << 5)) { // level = 0
+ // we're already at the block start
+ } else if (xor < (1 << 10)) { // level = 1
if (depth == 1) {
display1 = new Array(32)
- display1((oldIndex >> 5) & 31) = display0
- depth +=1
+ display1((oldIndex >>> 5) & 31) = display0
+ depth += 1
}
display0 = new Array(32)
- } else
- if (xor < (1 << 15)) { // level = 2
+ } else if (xor < (1 << 15)) { // level = 2
if (depth == 2) {
display2 = new Array(32)
- display2((oldIndex >> 10) & 31) = display1
- depth +=1
+ display2((oldIndex >>> 10) & 31) = display1
+ depth += 1
}
- display1 = display2((newIndex >> 10) & 31).asInstanceOf[Array[AnyRef]]
+ display1 = display2((newIndex >>> 10) & 31).asInstanceOf[Array[AnyRef]]
if (display1 == null) display1 = new Array(32)
display0 = new Array(32)
- } else
- if (xor < (1 << 20)) { // level = 3
+ } else if (xor < (1 << 20)) { // level = 3
if (depth == 3) {
display3 = new Array(32)
- display3((oldIndex >> 15) & 31) = display2
- depth +=1
+ display3((oldIndex >>> 15) & 31) = display2
+ depth += 1
}
- display2 = display3((newIndex >> 15) & 31).asInstanceOf[Array[AnyRef]]
+ display2 = display3((newIndex >>> 15) & 31).asInstanceOf[Array[AnyRef]]
if (display2 == null) display2 = new Array(32)
- display1 = display2((newIndex >> 10) & 31).asInstanceOf[Array[AnyRef]]
+ display1 = display2((newIndex >>> 10) & 31).asInstanceOf[Array[AnyRef]]
if (display1 == null) display1 = new Array(32)
display0 = new Array(32)
- } else
- if (xor < (1 << 25)) { // level = 4
+ } else if (xor < (1 << 25)) { // level = 4
if (depth == 4) {
display4 = new Array(32)
- display4((oldIndex >> 20) & 31) = display3
- depth +=1
+ display4((oldIndex >>> 20) & 31) = display3
+ depth += 1
}
- display3 = display4((newIndex >> 20) & 31).asInstanceOf[Array[AnyRef]]
+ display3 = display4((newIndex >>> 20) & 31).asInstanceOf[Array[AnyRef]]
if (display3 == null) display3 = new Array(32)
- display2 = display3((newIndex >> 15) & 31).asInstanceOf[Array[AnyRef]]
+ display2 = display3((newIndex >>> 15) & 31).asInstanceOf[Array[AnyRef]]
if (display2 == null) display2 = new Array(32)
- display1 = display2((newIndex >> 10) & 31).asInstanceOf[Array[AnyRef]]
+ display1 = display2((newIndex >>> 10) & 31).asInstanceOf[Array[AnyRef]]
if (display1 == null) display1 = new Array(32)
display0 = new Array(32)
- } else
- if (xor < (1 << 30)) { // level = 5
+ } else if (xor < (1 << 30)) { // level = 5
if (depth == 5) {
display5 = new Array(32)
- display5((oldIndex >> 25) & 31) = display4
- depth +=1
+ display5((oldIndex >>> 25) & 31) = display4
+ depth += 1
}
- display4 = display5((newIndex >> 25) & 31).asInstanceOf[Array[AnyRef]]
+ display4 = display5((newIndex >>> 25) & 31).asInstanceOf[Array[AnyRef]]
if (display4 == null) display4 = new Array(32)
- display3 = display4((newIndex >> 20) & 31).asInstanceOf[Array[AnyRef]]
+ display3 = display4((newIndex >>> 20) & 31).asInstanceOf[Array[AnyRef]]
if (display3 == null) display3 = new Array(32)
- display2 = display3((newIndex >> 15) & 31).asInstanceOf[Array[AnyRef]]
+ display2 = display3((newIndex >>> 15) & 31).asInstanceOf[Array[AnyRef]]
if (display2 == null) display2 = new Array(32)
- display1 = display2((newIndex >> 10) & 31).asInstanceOf[Array[AnyRef]]
+ display1 = display2((newIndex >>> 10) & 31).asInstanceOf[Array[AnyRef]]
if (display1 == null) display1 = new Array(32)
display0 = new Array(32)
- } else { // level = 6
+ } else { // level = 6
throw new IllegalArgumentException()
}
}
-
// requires structure is dirty and at pos oldIndex,
// ensures structure is dirty and at pos newIndex and writable at level 0
private[immutable] final def gotoFreshPosWritable1(oldIndex: Int, newIndex: Int, xor: Int): Unit = {
stabilize(oldIndex)
gotoFreshPosWritable0(oldIndex, newIndex, xor)
}
-
-
-
-
- // DEBUG STUFF
-
- private[immutable] def debug(): Unit = {
- return
-/*
- //println("DISPLAY 5: " + display5 + " ---> " + (if (display5 ne null) display5.map(x=> if (x eq null) "." else x + "->" +x.asInstanceOf[Array[AnyRef]].mkString("")).mkString(" ") else "null"))
- //println("DISPLAY 4: " + display4 + " ---> " + (if (display4 ne null) display4.map(x=> if (x eq null) "." else x + "->" +x.asInstanceOf[Array[AnyRef]].mkString("")).mkString(" ") else "null"))
- //println("DISPLAY 3: " + display3 + " ---> " + (if (display3 ne null) display3.map(x=> if (x eq null) "." else x + "->" +x.asInstanceOf[Array[AnyRef]].mkString("")).mkString(" ") else "null"))
- //println("DISPLAY 2: " + display2 + " ---> " + (if (display2 ne null) display2.map(x=> if (x eq null) "." else x + "->" +x.asInstanceOf[Array[AnyRef]].mkString("")).mkString(" ") else "null"))
- //println("DISPLAY 1: " + display1 + " ---> " + (if (display1 ne null) display1.map(x=> if (x eq null) "." else x + "->" +x.asInstanceOf[Array[AnyRef]].mkString("")).mkString(" ") else "null"))
- //println("DISPLAY 0: " + display0 + " ---> " + (if (display0 ne null) display0.map(x=> if (x eq null) "." else x.toString).mkString(" ") else "null"))
-*/
- //println("DISPLAY 5: " + (if (display5 ne null) display5.map(x=> if (x eq null) "." else x.asInstanceOf[Array[AnyRef]].deepMkString("[","","]")).mkString(" ") else "null"))
- //println("DISPLAY 4: " + (if (display4 ne null) display4.map(x=> if (x eq null) "." else x.asInstanceOf[Array[AnyRef]].deepMkString("[","","]")).mkString(" ") else "null"))
- //println("DISPLAY 3: " + (if (display3 ne null) display3.map(x=> if (x eq null) "." else x.asInstanceOf[Array[AnyRef]].deepMkString("[","","]")).mkString(" ") else "null"))
- //println("DISPLAY 2: " + (if (display2 ne null) display2.map(x=> if (x eq null) "." else x.asInstanceOf[Array[AnyRef]].deepMkString("[","","]")).mkString(" ") else "null"))
- //println("DISPLAY 1: " + (if (display1 ne null) display1.map(x=> if (x eq null) "." else x.asInstanceOf[Array[AnyRef]].deepMkString("[","","]")).mkString(" ") else "null"))
- //println("DISPLAY 0: " + (if (display0 ne null) display0.map(x=> if (x eq null) "." else x.toString).mkString(" ") else "null"))
- }
-
-
}
-
diff --git a/src/library/scala/collection/immutable/WrappedString.scala b/src/library/scala/collection/immutable/WrappedString.scala
index 7592316650..8726bd2ed9 100644
--- a/src/library/scala/collection/immutable/WrappedString.scala
+++ b/src/library/scala/collection/immutable/WrappedString.scala
@@ -29,8 +29,7 @@ import mutable.{Builder, StringBuilder}
* @define Coll `WrappedString`
* @define coll wrapped string
*/
-@deprecatedInheritance("Inherit from StringLike instead of WrappedString.", "2.11.0")
-class WrappedString(val self: String) extends AbstractSeq[Char] with IndexedSeq[Char] with StringLike[WrappedString] {
+final class WrappedString(val self: String) extends AbstractSeq[Char] with IndexedSeq[Char] with StringLike[WrappedString] {
override protected[this] def thisCollection: WrappedString = this
override protected[this] def toCollection(repr: WrappedString): WrappedString = repr
diff --git a/src/library/scala/collection/mutable/AVLTree.scala b/src/library/scala/collection/mutable/AVLTree.scala
deleted file mode 100644
index b63d0aae33..0000000000
--- a/src/library/scala/collection/mutable/AVLTree.scala
+++ /dev/null
@@ -1,250 +0,0 @@
-/* __ *\
-** ________ ___ / / ___ Scala API **
-** / __/ __// _ | / / / _ | (c) 2003-2013, LAMP/EPFL **
-** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ **
-** /____/\___/_/ |_/____/_/ | | **
-** |/ **
-\* */
-
-package scala
-package collection
-package mutable
-
-/**
- * An immutable AVL Tree implementation formerly used by mutable.TreeSet
- *
- * @author Lucien Pereira
- */
-@deprecated("AVLTree and its related classes are being removed from the standard library since they're not different enough from RedBlackTree to justify keeping them.", "2.11.2")
-private[mutable] sealed trait AVLTree[+A] extends Serializable {
- def balance: Int
-
- def depth: Int
-
- def iterator[B >: A]: Iterator[B] = Iterator.empty
-
- def contains[B >: A](value: B, ordering: Ordering[B]): Boolean = false
-
- /**
- * Returns a new tree containing the given element.
- * Throws an IllegalArgumentException if element is already present.
- *
- */
- def insert[B >: A](value: B, ordering: Ordering[B]): AVLTree[B] = Node(value, Leaf, Leaf)
-
- /**
- * Return a new tree which not contains given element.
- *
- */
- def remove[B >: A](value: B, ordering: Ordering[B]): AVLTree[A] =
- throw new NoSuchElementException(String.valueOf(value))
-
- /**
- * Return a tuple containing the smallest element of the provided tree
- * and a new tree from which this element has been extracted.
- *
- */
- def removeMin[B >: A]: (B, AVLTree[B]) = sys.error("Should not happen.")
-
- /**
- * Return a tuple containing the biggest element of the provided tree
- * and a new tree from which this element has been extracted.
- *
- */
- def removeMax[B >: A]: (B, AVLTree[B]) = sys.error("Should not happen.")
-
- def rebalance[B >: A]: AVLTree[B] = this
-
- def leftRotation[B >: A]: Node[B] = sys.error("Should not happen.")
-
- def rightRotation[B >: A]: Node[B] = sys.error("Should not happen.")
-
- def doubleLeftRotation[B >: A]: Node[B] = sys.error("Should not happen.")
-
- def doubleRightRotation[B >: A]: Node[B] = sys.error("Should not happen.")
-}
-
-/**
- * @deprecated("AVLTree and its related classes are being removed from the standard library since they're not different enough from RedBlackTree to justify keeping them.", "2.11.0")
- */
-private case object Leaf extends AVLTree[Nothing] {
- override val balance: Int = 0
-
- override val depth: Int = -1
-}
-
-/**
- * @deprecated("AVLTree and its related classes are being removed from the standard library since they're not different enough from RedBlackTree to justify keeping them.", "2.11.0")
- */
-private case class Node[A](data: A, left: AVLTree[A], right: AVLTree[A]) extends AVLTree[A] {
- override val balance: Int = right.depth - left.depth
-
- override val depth: Int = math.max(left.depth, right.depth) + 1
-
- override def iterator[B >: A]: Iterator[B] = new AVLIterator(this)
-
- override def contains[B >: A](value: B, ordering: Ordering[B]) = {
- val ord = ordering.compare(value, data)
- if (0 == ord)
- true
- else if (ord < 0)
- left.contains(value, ordering)
- else
- right.contains(value, ordering)
- }
-
- /**
- * Returns a new tree containing the given element.
- * Throws an IllegalArgumentException if element is already present.
- *
- */
- override def insert[B >: A](value: B, ordering: Ordering[B]) = {
- val ord = ordering.compare(value, data)
- if (0 == ord)
- throw new IllegalArgumentException()
- else if (ord < 0)
- Node(data, left.insert(value, ordering), right).rebalance
- else
- Node(data, left, right.insert(value, ordering)).rebalance
- }
-
- /**
- * Return a new tree which not contains given element.
- *
- */
- override def remove[B >: A](value: B, ordering: Ordering[B]): AVLTree[A] = {
- val ord = ordering.compare(value, data)
- if(ord == 0) {
- if (Leaf == left) {
- if (Leaf == right) {
- Leaf
- } else {
- val (min, newRight) = right.removeMin
- Node(min, left, newRight).rebalance
- }
- } else {
- val (max, newLeft) = left.removeMax
- Node(max, newLeft, right).rebalance
- }
- } else if (ord < 0) {
- Node(data, left.remove(value, ordering), right).rebalance
- } else {
- Node(data, left, right.remove(value, ordering)).rebalance
- }
- }
-
- /**
- * Return a tuple containing the smallest element of the provided tree
- * and a new tree from which this element has been extracted.
- *
- */
- override def removeMin[B >: A]: (B, AVLTree[B]) = {
- if (Leaf == left)
- (data, right)
- else {
- val (min, newLeft) = left.removeMin
- (min, Node(data, newLeft, right).rebalance)
- }
- }
-
- /**
- * Return a tuple containing the biggest element of the provided tree
- * and a new tree from which this element has been extracted.
- *
- */
- override def removeMax[B >: A]: (B, AVLTree[B]) = {
- if (Leaf == right)
- (data, left)
- else {
- val (max, newRight) = right.removeMax
- (max, Node(data, left, newRight).rebalance)
- }
- }
-
- override def rebalance[B >: A] = {
- if (-2 == balance) {
- if (1 == left.balance)
- doubleRightRotation
- else
- rightRotation
- } else if (2 == balance) {
- if (-1 == right.balance)
- doubleLeftRotation
- else
- leftRotation
- } else {
- this
- }
- }
-
- override def leftRotation[B >: A] = {
- if (Leaf != right) {
- val r: Node[A] = right.asInstanceOf[Node[A]]
- Node(r.data, Node(data, left, r.left), r.right)
- } else sys.error("Should not happen.")
- }
-
- override def rightRotation[B >: A] = {
- if (Leaf != left) {
- val l: Node[A] = left.asInstanceOf[Node[A]]
- Node(l.data, l.left, Node(data, l.right, right))
- } else sys.error("Should not happen.")
- }
-
- override def doubleLeftRotation[B >: A] = {
- if (Leaf != right) {
- val r: Node[A] = right.asInstanceOf[Node[A]]
- // Let's save an instanceOf by 'inlining' the left rotation
- val rightRotated = r.rightRotation
- Node(rightRotated.data, Node(data, left, rightRotated.left), rightRotated.right)
- } else sys.error("Should not happen.")
- }
-
- override def doubleRightRotation[B >: A] = {
- if (Leaf != left) {
- val l: Node[A] = left.asInstanceOf[Node[A]]
- // Let's save an instanceOf by 'inlining' the right rotation
- val leftRotated = l.leftRotation
- Node(leftRotated.data, leftRotated.left, Node(data, leftRotated.right, right))
- } else sys.error("Should not happen.")
- }
-}
-
-/**
- * @deprecated("AVLTree and its related classes are being removed from the standard library since they're not different enough from RedBlackTree to justify keeping them.", "2.11.0")
- */
-private class AVLIterator[A](root: Node[A]) extends Iterator[A] {
- val stack = mutable.ArrayStack[Node[A]](root)
- diveLeft()
-
- private def diveLeft(): Unit = {
- if (Leaf != stack.head.left) {
- val left: Node[A] = stack.head.left.asInstanceOf[Node[A]]
- stack.push(left)
- diveLeft()
- }
- }
-
- private def engageRight(): Unit = {
- if (Leaf != stack.head.right) {
- val right: Node[A] = stack.head.right.asInstanceOf[Node[A]]
- stack.pop()
- stack.push(right)
- diveLeft()
- } else
- stack.pop()
- }
-
- override def hasNext: Boolean = !stack.isEmpty
-
- override def next(): A = {
- if (stack.isEmpty)
- throw new NoSuchElementException()
- else {
- val result = stack.head.data
- // Let's maintain stack for the next invocation
- engageRight()
- result
- }
- }
-}
diff --git a/src/library/scala/collection/mutable/AnyRefMap.scala b/src/library/scala/collection/mutable/AnyRefMap.scala
index 369d596ec3..6ff79dd1b8 100644
--- a/src/library/scala/collection/mutable/AnyRefMap.scala
+++ b/src/library/scala/collection/mutable/AnyRefMap.scala
@@ -27,10 +27,12 @@ import generic.CanBuildFrom
* rapidly as 2^30^ is approached.
*
*/
+@SerialVersionUID(1L)
final class AnyRefMap[K <: AnyRef, V] private[collection] (defaultEntry: K => V, initialBufferSize: Int, initBlank: Boolean)
extends AbstractMap[K, V]
with Map[K, V]
with MapLike[K, V, AnyRefMap[K, V]]
+ with Serializable
{
import AnyRefMap._
def this() = this(AnyRefMap.exceptionDefault, 16, true)
@@ -335,6 +337,24 @@ extends AbstractMap[K, V]
arm
}
+ override def +[V1 >: V](kv: (K, V1)): AnyRefMap[K, V1] = {
+ val arm = clone().asInstanceOf[AnyRefMap[K, V1]]
+ arm += kv
+ arm
+ }
+
+ override def ++[V1 >: V](xs: GenTraversableOnce[(K, V1)]): AnyRefMap[K, V1] = {
+ val arm = clone().asInstanceOf[AnyRefMap[K, V1]]
+ xs.foreach(kv => arm += kv)
+ arm
+ }
+
+ override def updated[V1 >: V](key: K, value: V1): AnyRefMap[K, V1] = {
+ val arm = clone().asInstanceOf[AnyRefMap[K, V1]]
+ arm += (key, value)
+ arm
+ }
+
private[this] def foreachElement[A,B](elems: Array[AnyRef], f: A => B) {
var i,j = 0
while (i < _hashes.length & j < _size) {
@@ -399,7 +419,11 @@ object AnyRefMap {
private final val VacantBit = 0x40000000
private final val MissVacant = 0xC0000000
- private val exceptionDefault = (k: Any) => throw new NoSuchElementException(if (k == null) "(null)" else k.toString)
+ @SerialVersionUID(1L)
+ private class ExceptionDefault extends (Any => Nothing) with Serializable {
+ def apply(k: Any): Nothing = throw new NoSuchElementException(if (k == null) "(null)" else k.toString)
+ }
+ private val exceptionDefault = new ExceptionDefault
implicit def canBuildFrom[K <: AnyRef, V, J <: AnyRef, U]: CanBuildFrom[AnyRefMap[K,V], (J, U), AnyRefMap[J,U]] =
new CanBuildFrom[AnyRefMap[K,V], (J, U), AnyRefMap[J,U]] {
@@ -407,7 +431,11 @@ object AnyRefMap {
def apply(): AnyRefMapBuilder[J, U] = new AnyRefMapBuilder[J, U]
}
- final class AnyRefMapBuilder[K <: AnyRef, V] extends Builder[(K, V), AnyRefMap[K, V]] {
+ /** A builder for instances of `AnyRefMap`.
+ *
+ * This builder can be reused to create multiple instances.
+ */
+ final class AnyRefMapBuilder[K <: AnyRef, V] extends ReusableBuilder[(K, V), AnyRefMap[K, V]] {
private[collection] var elems: AnyRefMap[K, V] = new AnyRefMap[K, V]
def +=(entry: (K, V)): this.type = {
elems += entry
diff --git a/src/library/scala/collection/mutable/ArrayBuffer.scala b/src/library/scala/collection/mutable/ArrayBuffer.scala
index 011fd415ee..23d386f729 100644
--- a/src/library/scala/collection/mutable/ArrayBuffer.scala
+++ b/src/library/scala/collection/mutable/ArrayBuffer.scala
@@ -67,7 +67,7 @@ class ArrayBuffer[A](override protected val initialSize: Int)
override def sizeHint(len: Int) {
if (len > size && len >= 1) {
val newarray = new Array[AnyRef](len)
- scala.compat.Platform.arraycopy(array, 0, newarray, 0, size0)
+ java.lang.System.arraycopy(array, 0, newarray, 0, size0)
array = newarray
}
}
@@ -149,13 +149,16 @@ class ArrayBuffer[A](override protected val initialSize: Int)
/** Removes the element on a given index position. It takes time linear in
* the buffer size.
*
- * @param n the index which refers to the first element to delete.
- * @param count the number of elements to delete
- * @throws IndexOutOfBoundsException if `n` is out of bounds.
+ * @param n the index which refers to the first element to remove.
+ * @param count the number of elements to remove.
+ * @throws IndexOutOfBoundsException if the index `n` is not in the valid range
+ * `0 <= n <= length - count` (with `count > 0`).
+ * @throws IllegalArgumentException if `count < 0`.
*/
override def remove(n: Int, count: Int) {
- require(count >= 0, "removing negative number of elements")
- if (n < 0 || n > size0 - count) throw new IndexOutOfBoundsException(n.toString)
+ if (count < 0) throw new IllegalArgumentException("removing negative number of elements: " + count.toString)
+ else if (count == 0) return // Did nothing
+ if (n < 0 || n > size0 - count) throw new IndexOutOfBoundsException("at " + n.toString + " deleting " + count.toString)
copy(n + count, n, size0 - (n + count))
reduceToSize(size0 - count)
}
diff --git a/src/library/scala/collection/mutable/ArrayBuilder.scala b/src/library/scala/collection/mutable/ArrayBuilder.scala
index f4ca27dcba..d023110c1b 100644
--- a/src/library/scala/collection/mutable/ArrayBuilder.scala
+++ b/src/library/scala/collection/mutable/ArrayBuilder.scala
@@ -11,7 +11,6 @@ package collection
package mutable
import scala.reflect.ClassTag
-import scala.runtime.ScalaRunTime
/** A builder class for arrays.
*
@@ -19,7 +18,7 @@ import scala.runtime.ScalaRunTime
*
* @tparam T the type of the elements for the builder.
*/
-abstract class ArrayBuilder[T] extends Builder[T, Array[T]] with Serializable
+abstract class ArrayBuilder[T] extends ReusableBuilder[T, Array[T]] with Serializable
/** A companion object for array builders.
*
@@ -50,10 +49,11 @@ object ArrayBuilder {
/** A class for array builders for arrays of reference types.
*
+ * This builder can be reused.
+ *
* @tparam T type of elements for the array builder, subtype of `AnyRef` with a `ClassTag` context bound.
*/
- @deprecatedInheritance("ArrayBuilder.ofRef is an internal implementation not intended for subclassing.", "2.11.0")
- class ofRef[T <: AnyRef : ClassTag] extends ArrayBuilder[T] {
+ final class ofRef[T <: AnyRef : ClassTag] extends ArrayBuilder[T] {
private var elems: Array[T] = _
private var capacity: Int = 0
@@ -99,9 +99,7 @@ object ArrayBuilder {
super.++=(xs)
}
- def clear() {
- size = 0
- }
+ def clear() { size = 0 }
def result() = {
if (capacity != 0 && capacity == size) {
@@ -119,9 +117,8 @@ object ArrayBuilder {
override def toString = "ArrayBuilder.ofRef"
}
- /** A class for array builders for arrays of `byte`s. */
- @deprecatedInheritance("ArrayBuilder.ofByte is an internal implementation not intended for subclassing.", "2.11.0")
- class ofByte extends ArrayBuilder[Byte] {
+ /** A class for array builders for arrays of `byte`s. It can be reused. */
+ final class ofByte extends ArrayBuilder[Byte] {
private var elems: Array[Byte] = _
private var capacity: Int = 0
@@ -167,9 +164,7 @@ object ArrayBuilder {
super.++=(xs)
}
- def clear() {
- size = 0
- }
+ def clear() { size = 0 }
def result() = {
if (capacity != 0 && capacity == size) {
@@ -187,9 +182,8 @@ object ArrayBuilder {
override def toString = "ArrayBuilder.ofByte"
}
- /** A class for array builders for arrays of `short`s. */
- @deprecatedInheritance("ArrayBuilder.ofShort is an internal implementation not intended for subclassing.", "2.11.0")
- class ofShort extends ArrayBuilder[Short] {
+ /** A class for array builders for arrays of `short`s. It can be reused. */
+ final class ofShort extends ArrayBuilder[Short] {
private var elems: Array[Short] = _
private var capacity: Int = 0
@@ -235,9 +229,7 @@ object ArrayBuilder {
super.++=(xs)
}
- def clear() {
- size = 0
- }
+ def clear() { size = 0 }
def result() = {
if (capacity != 0 && capacity == size) {
@@ -255,9 +247,8 @@ object ArrayBuilder {
override def toString = "ArrayBuilder.ofShort"
}
- /** A class for array builders for arrays of `char`s. */
- @deprecatedInheritance("ArrayBuilder.ofChar is an internal implementation not intended for subclassing.", "2.11.0")
- class ofChar extends ArrayBuilder[Char] {
+ /** A class for array builders for arrays of `char`s. It can be reused. */
+ final class ofChar extends ArrayBuilder[Char] {
private var elems: Array[Char] = _
private var capacity: Int = 0
@@ -303,9 +294,7 @@ object ArrayBuilder {
super.++=(xs)
}
- def clear() {
- size = 0
- }
+ def clear() { size = 0 }
def result() = {
if (capacity != 0 && capacity == size) {
@@ -323,9 +312,8 @@ object ArrayBuilder {
override def toString = "ArrayBuilder.ofChar"
}
- /** A class for array builders for arrays of `int`s. */
- @deprecatedInheritance("ArrayBuilder.ofInt is an internal implementation not intended for subclassing.", "2.11.0")
- class ofInt extends ArrayBuilder[Int] {
+ /** A class for array builders for arrays of `int`s. It can be reused. */
+ final class ofInt extends ArrayBuilder[Int] {
private var elems: Array[Int] = _
private var capacity: Int = 0
@@ -371,9 +359,7 @@ object ArrayBuilder {
super.++=(xs)
}
- def clear() {
- size = 0
- }
+ def clear() { size = 0 }
def result() = {
if (capacity != 0 && capacity == size) {
@@ -391,9 +377,8 @@ object ArrayBuilder {
override def toString = "ArrayBuilder.ofInt"
}
- /** A class for array builders for arrays of `long`s. */
- @deprecatedInheritance("ArrayBuilder.ofLong is an internal implementation not intended for subclassing.", "2.11.0")
- class ofLong extends ArrayBuilder[Long] {
+ /** A class for array builders for arrays of `long`s. It can be reused. */
+ final class ofLong extends ArrayBuilder[Long] {
private var elems: Array[Long] = _
private var capacity: Int = 0
@@ -439,9 +424,7 @@ object ArrayBuilder {
super.++=(xs)
}
- def clear() {
- size = 0
- }
+ def clear() { size = 0 }
def result() = {
if (capacity != 0 && capacity == size) {
@@ -459,9 +442,8 @@ object ArrayBuilder {
override def toString = "ArrayBuilder.ofLong"
}
- /** A class for array builders for arrays of `float`s. */
- @deprecatedInheritance("ArrayBuilder.ofFloat is an internal implementation not intended for subclassing.", "2.11.0")
- class ofFloat extends ArrayBuilder[Float] {
+ /** A class for array builders for arrays of `float`s. It can be reused. */
+ final class ofFloat extends ArrayBuilder[Float] {
private var elems: Array[Float] = _
private var capacity: Int = 0
@@ -507,9 +489,7 @@ object ArrayBuilder {
super.++=(xs)
}
- def clear() {
- size = 0
- }
+ def clear() { size = 0 }
def result() = {
if (capacity != 0 && capacity == size) {
@@ -527,9 +507,8 @@ object ArrayBuilder {
override def toString = "ArrayBuilder.ofFloat"
}
- /** A class for array builders for arrays of `double`s. */
- @deprecatedInheritance("ArrayBuilder.ofDouble is an internal implementation not intended for subclassing.", "2.11.0")
- class ofDouble extends ArrayBuilder[Double] {
+ /** A class for array builders for arrays of `double`s. It can be reused. */
+ final class ofDouble extends ArrayBuilder[Double] {
private var elems: Array[Double] = _
private var capacity: Int = 0
@@ -575,9 +554,7 @@ object ArrayBuilder {
super.++=(xs)
}
- def clear() {
- size = 0
- }
+ def clear() { size = 0 }
def result() = {
if (capacity != 0 && capacity == size) {
@@ -595,7 +572,7 @@ object ArrayBuilder {
override def toString = "ArrayBuilder.ofDouble"
}
- /** A class for array builders for arrays of `boolean`s. */
+ /** A class for array builders for arrays of `boolean`s. It can be reused. */
class ofBoolean extends ArrayBuilder[Boolean] {
private var elems: Array[Boolean] = _
@@ -642,9 +619,7 @@ object ArrayBuilder {
super.++=(xs)
}
- def clear() {
- size = 0
- }
+ def clear() { size = 0 }
def result() = {
if (capacity != 0 && capacity == size) {
@@ -662,68 +637,32 @@ object ArrayBuilder {
override def toString = "ArrayBuilder.ofBoolean"
}
- /** A class for array builders for arrays of `Unit` type. */
- @deprecatedInheritance("ArrayBuilder.ofUnit is an internal implementation not intended for subclassing.", "2.11.0")
- class ofUnit extends ArrayBuilder[Unit] {
+ /** A class for array builders for arrays of `Unit` type. It can be reused. */
+ final class ofUnit extends ArrayBuilder[Unit] {
- private var elems: Array[Unit] = _
- private var capacity: Int = 0
private var size: Int = 0
- private def mkArray(size: Int): Array[Unit] = {
- val newelems = new Array[Unit](size)
- if (this.size > 0) Array.copy(elems, 0, newelems, 0, this.size)
- newelems
- }
-
- private def resize(size: Int) {
- elems = mkArray(size)
- capacity = size
- }
-
- override def sizeHint(size: Int) {
- if (capacity < size) resize(size)
- }
-
- private def ensureSize(size: Int) {
- if (capacity < size || capacity == 0) {
- var newsize = if (capacity == 0) 16 else capacity * 2
- while (newsize < size) newsize *= 2
- resize(newsize)
- }
- }
-
def +=(elem: Unit): this.type = {
- ensureSize(size + 1)
- elems(size) = elem
size += 1
this
}
- override def ++=(xs: TraversableOnce[Unit]): this.type = xs match {
- case xs: WrappedArray.ofUnit =>
- ensureSize(this.size + xs.length)
- Array.copy(xs.array, 0, elems, this.size, xs.length)
- size += xs.length
- this
- case _ =>
- super.++=(xs)
+ override def ++=(xs: TraversableOnce[Unit]): this.type = {
+ size += xs.size
+ this
}
- def clear() {
- size = 0
- }
+ def clear() { size = 0 }
def result() = {
- if (capacity != 0 && capacity == size) {
- capacity = 0
- elems
- }
- else mkArray(size)
+ val ans = new Array[Unit](size)
+ var i = 0
+ while (i < size) { ans(i) = (); i += 1 }
+ ans
}
override def equals(other: Any): Boolean = other match {
- case x: ofUnit => (size == x.size) && (elems == x.elems)
+ case x: ofUnit => (size == x.size)
case _ => false
}
diff --git a/src/library/scala/collection/mutable/ArrayOps.scala b/src/library/scala/collection/mutable/ArrayOps.scala
index 00491ef20e..0f83fd92c1 100644
--- a/src/library/scala/collection/mutable/ArrayOps.scala
+++ b/src/library/scala/collection/mutable/ArrayOps.scala
@@ -10,9 +10,7 @@ package scala
package collection
package mutable
-import scala.compat.Platform.arraycopy
import scala.reflect.ClassTag
-import scala.runtime.ScalaRunTime._
import parallel.mutable.ParArray
/** This class serves as a wrapper for `Array`s with all the operations found in
@@ -33,20 +31,29 @@ import parallel.mutable.ParArray
* @define mayNotTerminateInf
* @define willNotTerminateInf
*/
-@deprecatedInheritance("ArrayOps will be sealed to facilitate greater flexibility with array/collections integration in future releases.", "2.11.0")
-trait ArrayOps[T] extends Any with ArrayLike[T, Array[T]] with CustomParallelizable[T, ParArray[T]] {
+sealed trait ArrayOps[T] extends Any with ArrayLike[T, Array[T]] with CustomParallelizable[T, ParArray[T]] {
private def elementClass: Class[_] =
- arrayElementClass(repr.getClass)
+ repr.getClass.getComponentType
override def copyToArray[U >: T](xs: Array[U], start: Int, len: Int) {
- var l = math.min(len, repr.length)
- if (xs.length - start < l) l = xs.length - start max 0
- Array.copy(repr, 0, xs, start, l)
+ val l = len min repr.length min (xs.length - start)
+ if (l > 0) Array.copy(repr, 0, xs, start, l)
+ }
+
+ override def slice(from: Int, until: Int): Array[T] = {
+ val lo = math.max(from, 0)
+ val hi = math.min(math.max(until, 0), repr.length)
+ val size = math.max(hi - lo, 0)
+ val result = java.lang.reflect.Array.newInstance(elementClass, size)
+ if (size > 0) {
+ Array.copy(repr, lo, result, 0, size)
+ }
+ result.asInstanceOf[Array[T]]
}
override def toArray[U >: T : ClassTag]: Array[U] = {
- val thatElementClass = arrayElementClass(implicitly[ClassTag[U]])
+ val thatElementClass = implicitly[ClassTag[U]].runtimeClass
if (elementClass eq thatElementClass)
repr.asInstanceOf[Array[U]]
else
@@ -94,7 +101,7 @@ trait ArrayOps[T] extends Any with ArrayLike[T, Array[T]] with CustomParalleliza
val bb: Builder[Array[U], Array[Array[U]]] = Array.newBuilder(ClassTag[Array[U]](elementClass))
if (isEmpty) bb.result()
else {
- def mkRowBuilder() = Array.newBuilder(ClassTag[U](arrayElementClass(elementClass)))
+ def mkRowBuilder() = Array.newBuilder(ClassTag[U](elementClass.getComponentType))
val bs = asArray(head) map (_ => mkRowBuilder())
for (xs <- this) {
var i = 0
@@ -107,9 +114,9 @@ trait ArrayOps[T] extends Any with ArrayLike[T, Array[T]] with CustomParalleliza
bb.result()
}
}
-
+
/** Converts an array of pairs into an array of first elements and an array of second elements.
- *
+ *
* @tparam T1 the type of the first half of the element pairs
* @tparam T2 the type of the second half of the element pairs
* @param asPair an implicit conversion which asserts that the element type
@@ -135,9 +142,9 @@ trait ArrayOps[T] extends Any with ArrayLike[T, Array[T]] with CustomParalleliza
}
(a1, a2)
}
-
+
/** Converts an array of triples into three arrays, one containing the elements from each position of the triple.
- *
+ *
* @tparam T1 the type of the first of three elements in the triple
* @tparam T2 the type of the second of three elements in the triple
* @tparam T3 the type of the third of three elements in the triple
@@ -169,10 +176,8 @@ trait ArrayOps[T] extends Any with ArrayLike[T, Array[T]] with CustomParalleliza
}
(a1, a2, a3)
}
-
def seq = thisCollection
-
}
/**
@@ -187,15 +192,15 @@ object ArrayOps {
override protected[this] def thisCollection: WrappedArray[T] = new WrappedArray.ofRef[T](repr)
override protected[this] def toCollection(repr: Array[T]): WrappedArray[T] = new WrappedArray.ofRef[T](repr)
- override protected[this] def newBuilder = new ArrayBuilder.ofRef[T]()(ClassTag[T](arrayElementClass(repr.getClass)))
+ override protected[this] def newBuilder = new ArrayBuilder.ofRef[T]()(ClassTag[T](repr.getClass.getComponentType))
def length: Int = repr.length
def apply(index: Int): T = repr(index)
def update(index: Int, elem: T) { repr(index) = elem }
}
- /** A class of `ArrayOps` for arrays containing `byte`s. */
-final class ofByte(override val repr: Array[Byte]) extends AnyVal with ArrayOps[Byte] with ArrayLike[Byte, Array[Byte]] {
+ /** A subclass of `ArrayOps` for arrays containing `Byte`s. */
+ final class ofByte(override val repr: Array[Byte]) extends AnyVal with ArrayOps[Byte] with ArrayLike[Byte, Array[Byte]] {
override protected[this] def thisCollection: WrappedArray[Byte] = new WrappedArray.ofByte(repr)
override protected[this] def toCollection(repr: Array[Byte]): WrappedArray[Byte] = new WrappedArray.ofByte(repr)
@@ -206,8 +211,8 @@ final class ofByte(override val repr: Array[Byte]) extends AnyVal with ArrayOps[
def update(index: Int, elem: Byte) { repr(index) = elem }
}
- /** A class of `ArrayOps` for arrays containing `short`s. */
-final class ofShort(override val repr: Array[Short]) extends AnyVal with ArrayOps[Short] with ArrayLike[Short, Array[Short]] {
+ /** A subclass of `ArrayOps` for arrays containing `Short`s. */
+ final class ofShort(override val repr: Array[Short]) extends AnyVal with ArrayOps[Short] with ArrayLike[Short, Array[Short]] {
override protected[this] def thisCollection: WrappedArray[Short] = new WrappedArray.ofShort(repr)
override protected[this] def toCollection(repr: Array[Short]): WrappedArray[Short] = new WrappedArray.ofShort(repr)
@@ -218,8 +223,8 @@ final class ofShort(override val repr: Array[Short]) extends AnyVal with ArrayOp
def update(index: Int, elem: Short) { repr(index) = elem }
}
- /** A class of `ArrayOps` for arrays containing `char`s. */
-final class ofChar(override val repr: Array[Char]) extends AnyVal with ArrayOps[Char] with ArrayLike[Char, Array[Char]] {
+ /** A subclass of `ArrayOps` for arrays containing `Char`s. */
+ final class ofChar(override val repr: Array[Char]) extends AnyVal with ArrayOps[Char] with ArrayLike[Char, Array[Char]] {
override protected[this] def thisCollection: WrappedArray[Char] = new WrappedArray.ofChar(repr)
override protected[this] def toCollection(repr: Array[Char]): WrappedArray[Char] = new WrappedArray.ofChar(repr)
@@ -230,8 +235,8 @@ final class ofChar(override val repr: Array[Char]) extends AnyVal with ArrayOps[
def update(index: Int, elem: Char) { repr(index) = elem }
}
- /** A class of `ArrayOps` for arrays containing `int`s. */
-final class ofInt(override val repr: Array[Int]) extends AnyVal with ArrayOps[Int] with ArrayLike[Int, Array[Int]] {
+ /** A subclass of `ArrayOps` for arrays containing `Int`s. */
+ final class ofInt(override val repr: Array[Int]) extends AnyVal with ArrayOps[Int] with ArrayLike[Int, Array[Int]] {
override protected[this] def thisCollection: WrappedArray[Int] = new WrappedArray.ofInt(repr)
override protected[this] def toCollection(repr: Array[Int]): WrappedArray[Int] = new WrappedArray.ofInt(repr)
@@ -242,8 +247,8 @@ final class ofInt(override val repr: Array[Int]) extends AnyVal with ArrayOps[In
def update(index: Int, elem: Int) { repr(index) = elem }
}
- /** A class of `ArrayOps` for arrays containing `long`s. */
-final class ofLong(override val repr: Array[Long]) extends AnyVal with ArrayOps[Long] with ArrayLike[Long, Array[Long]] {
+ /** A subclass of `ArrayOps` for arrays containing `Long`s. */
+ final class ofLong(override val repr: Array[Long]) extends AnyVal with ArrayOps[Long] with ArrayLike[Long, Array[Long]] {
override protected[this] def thisCollection: WrappedArray[Long] = new WrappedArray.ofLong(repr)
override protected[this] def toCollection(repr: Array[Long]): WrappedArray[Long] = new WrappedArray.ofLong(repr)
@@ -254,8 +259,8 @@ final class ofLong(override val repr: Array[Long]) extends AnyVal with ArrayOps[
def update(index: Int, elem: Long) { repr(index) = elem }
}
- /** A class of `ArrayOps` for arrays containing `float`s. */
-final class ofFloat(override val repr: Array[Float]) extends AnyVal with ArrayOps[Float] with ArrayLike[Float, Array[Float]] {
+ /** A subclass of `ArrayOps` for arrays containing `Float`s. */
+ final class ofFloat(override val repr: Array[Float]) extends AnyVal with ArrayOps[Float] with ArrayLike[Float, Array[Float]] {
override protected[this] def thisCollection: WrappedArray[Float] = new WrappedArray.ofFloat(repr)
override protected[this] def toCollection(repr: Array[Float]): WrappedArray[Float] = new WrappedArray.ofFloat(repr)
@@ -266,8 +271,8 @@ final class ofFloat(override val repr: Array[Float]) extends AnyVal with ArrayOp
def update(index: Int, elem: Float) { repr(index) = elem }
}
- /** A class of `ArrayOps` for arrays containing `double`s. */
-final class ofDouble(override val repr: Array[Double]) extends AnyVal with ArrayOps[Double] with ArrayLike[Double, Array[Double]] {
+ /** A subclass of `ArrayOps` for arrays containing `Double`s. */
+ final class ofDouble(override val repr: Array[Double]) extends AnyVal with ArrayOps[Double] with ArrayLike[Double, Array[Double]] {
override protected[this] def thisCollection: WrappedArray[Double] = new WrappedArray.ofDouble(repr)
override protected[this] def toCollection(repr: Array[Double]): WrappedArray[Double] = new WrappedArray.ofDouble(repr)
@@ -278,8 +283,8 @@ final class ofDouble(override val repr: Array[Double]) extends AnyVal with Array
def update(index: Int, elem: Double) { repr(index) = elem }
}
- /** A class of `ArrayOps` for arrays containing `boolean`s. */
-final class ofBoolean(override val repr: Array[Boolean]) extends AnyVal with ArrayOps[Boolean] with ArrayLike[Boolean, Array[Boolean]] {
+ /** A subclass of `ArrayOps` for arrays containing `Boolean`s. */
+ final class ofBoolean(override val repr: Array[Boolean]) extends AnyVal with ArrayOps[Boolean] with ArrayLike[Boolean, Array[Boolean]] {
override protected[this] def thisCollection: WrappedArray[Boolean] = new WrappedArray.ofBoolean(repr)
override protected[this] def toCollection(repr: Array[Boolean]): WrappedArray[Boolean] = new WrappedArray.ofBoolean(repr)
@@ -290,8 +295,8 @@ final class ofBoolean(override val repr: Array[Boolean]) extends AnyVal with Arr
def update(index: Int, elem: Boolean) { repr(index) = elem }
}
- /** A class of `ArrayOps` for arrays of `Unit` types. */
-final class ofUnit(override val repr: Array[Unit]) extends AnyVal with ArrayOps[Unit] with ArrayLike[Unit, Array[Unit]] {
+ /** A subclass of `ArrayOps` for arrays of `Unit` types. */
+ final class ofUnit(override val repr: Array[Unit]) extends AnyVal with ArrayOps[Unit] with ArrayLike[Unit, Array[Unit]] {
override protected[this] def thisCollection: WrappedArray[Unit] = new WrappedArray.ofUnit(repr)
override protected[this] def toCollection(repr: Array[Unit]): WrappedArray[Unit] = new WrappedArray.ofUnit(repr)
diff --git a/src/library/scala/collection/mutable/ArraySeq.scala b/src/library/scala/collection/mutable/ArraySeq.scala
index ddb48627af..1e82096baf 100644
--- a/src/library/scala/collection/mutable/ArraySeq.scala
+++ b/src/library/scala/collection/mutable/ArraySeq.scala
@@ -87,7 +87,7 @@ extends AbstractSeq[A]
*/
override def copyToArray[B >: A](xs: Array[B], start: Int, len: Int) {
val len1 = len min (xs.length - start) min length
- Array.copy(array, 0, xs, start, len1)
+ if (len1 > 0) Array.copy(array, 0, xs, start, len1)
}
override def clone(): ArraySeq[A] = {
diff --git a/src/library/scala/collection/mutable/ArrayStack.scala b/src/library/scala/collection/mutable/ArrayStack.scala
index 8ff128c026..951a90b084 100644
--- a/src/library/scala/collection/mutable/ArrayStack.scala
+++ b/src/library/scala/collection/mutable/ArrayStack.scala
@@ -64,9 +64,10 @@ object ArrayStack extends SeqFactory[ArrayStack] {
class ArrayStack[T] private(private var table : Array[AnyRef],
private var index : Int)
extends AbstractSeq[T]
- with Seq[T]
- with SeqLike[T, ArrayStack[T]]
+ with IndexedSeq[T]
+ with IndexedSeqLike[T, ArrayStack[T]]
with GenericTraversableTemplate[T, ArrayStack]
+ with IndexedSeqOptimized[T, ArrayStack[T]]
with Cloneable[ArrayStack[T]]
with Builder[T, ArrayStack[T]]
with Serializable
@@ -224,7 +225,7 @@ extends AbstractSeq[T]
/** Creates and iterator over the stack in LIFO order.
* @return an iterator over the elements of the stack.
*/
- def iterator: Iterator[T] = new AbstractIterator[T] {
+ override def iterator: Iterator[T] = new AbstractIterator[T] {
var currentIndex = index
def hasNext = currentIndex > 0
def next() = {
diff --git a/src/library/scala/collection/mutable/BitSet.scala b/src/library/scala/collection/mutable/BitSet.scala
index e92d48cfeb..e74ee65dda 100644
--- a/src/library/scala/collection/mutable/BitSet.scala
+++ b/src/library/scala/collection/mutable/BitSet.scala
@@ -13,7 +13,7 @@ package collection
package mutable
import generic._
-import BitSetLike.{LogWL, MaxSize, updateArray}
+import BitSetLike.{LogWL, MaxSize}
/** A class for mutable bitsets.
*
@@ -56,7 +56,7 @@ class BitSet(protected final var elems: Array[Long]) extends AbstractSet[Int]
@deprecatedOverriding("Internal implementation does not admit sensible overriding of this method.", "2.11.0")
protected def nwords = elems.length
-
+
@deprecatedOverriding("Internal implementation does not admit sensible overriding of this method.", "2.11.0")
protected def word(idx: Int): Long =
if (idx < nwords) elems(idx) else 0L
@@ -100,7 +100,7 @@ class BitSet(protected final var elems: Array[Long]) extends AbstractSet[Int]
@deprecatedOverriding("Override add to prevent += and add from exhibiting different behavior.", "2.11.0")
def += (elem: Int): this.type = { add(elem); this }
-
+
@deprecatedOverriding("Override add to prevent += and add from exhibiting different behavior.", "2.11.0")
def -= (elem: Int): this.type = { remove(elem); this }
@@ -164,7 +164,7 @@ class BitSet(protected final var elems: Array[Long]) extends AbstractSet[Int]
*/
@deprecated("If this BitSet contains a value that is 128 or greater, the result of this method is an 'immutable' " +
"BitSet that shares state with this mutable BitSet. Thus, if the mutable BitSet is modified, it will violate the " +
- "immutability of the result.", "2.11.6")
+ "immutability of the result.", "2.12.0")
def toImmutable = immutable.BitSet.fromBitMaskNoCopy(elems)
override def clone(): BitSet = {
diff --git a/src/library/scala/collection/mutable/BufferLike.scala b/src/library/scala/collection/mutable/BufferLike.scala
index 3c57387c03..c78d59297b 100644
--- a/src/library/scala/collection/mutable/BufferLike.scala
+++ b/src/library/scala/collection/mutable/BufferLike.scala
@@ -14,7 +14,7 @@ package mutable
import generic._
import script._
-import scala.annotation.{migration, bridge}
+import scala.annotation.migration
/** A template trait for buffers of type `Buffer[A]`.
*
@@ -105,15 +105,18 @@ trait BufferLike[A, +This <: BufferLike[A, This] with Buffer[A]]
*/
def remove(n: Int): A
- /** Removes a number of elements from a given index position.
+ /** Removes a number of elements from a given index position. Subclasses of `BufferLike`
+ * will typically override this method to provide better performance than `count`
+ * successive calls to single-element `remove`.
*
* @param n the index which refers to the first element to remove.
* @param count the number of elements to remove.
* @throws IndexOutOfBoundsException if the index `n` is not in the valid range
- * `0 <= n <= length - count`.
+ * `0 <= n <= length - count` (with `count > 0`).
* @throws IllegalArgumentException if `count < 0`.
*/
def remove(n: Int, count: Int) {
+ if (count < 0) throw new IllegalArgumentException("removing negative number of elements: " + count.toString)
for (i <- 0 until count) remove(n)
}
@@ -184,7 +187,7 @@ trait BufferLike[A, +This <: BufferLike[A, This] with Buffer[A]]
*
* @param cmd the message to send.
*/
- @deprecated("Scripting is deprecated.", "2.11.0")
+ @deprecated("scripting is deprecated", "2.11.0")
def <<(cmd: Message[A]): Unit = cmd match {
case Include(Start, x) => prepend(x)
case Include(End, x) => append(x)
@@ -211,13 +214,6 @@ trait BufferLike[A, +This <: BufferLike[A, This] with Buffer[A]]
*/
override def stringPrefix: String = "Buffer"
- /** Returns the current evolving(!) state of this buffer as a read-only sequence.
- *
- * @return A sequence that forwards to this buffer for all its operations.
- */
- @deprecated("The returned sequence changes as this buffer is mutated. For an immutable copy, use, e.g., toList.", "2.11.0")
- def readOnly: scala.collection.Seq[A] = toSeq
-
/** Creates a new collection containing both the elements of this collection and the provided
* traversable object.
*
diff --git a/src/library/scala/collection/mutable/BufferProxy.scala b/src/library/scala/collection/mutable/BufferProxy.scala
index d9632cce91..60f0e29746 100644
--- a/src/library/scala/collection/mutable/BufferProxy.scala
+++ b/src/library/scala/collection/mutable/BufferProxy.scala
@@ -26,7 +26,7 @@ import script._
* @define Coll `BufferProxy`
* @define coll buffer proxy
*/
-@deprecated("Proxying is deprecated due to lack of use and compiler-level support.", "2.11.0")
+@deprecated("proxying is deprecated due to lack of use and compiler-level support", "2.11.0")
trait BufferProxy[A] extends Buffer[A] with Proxy {
def self: Buffer[A]
@@ -43,8 +43,6 @@ trait BufferProxy[A] extends Buffer[A] with Proxy {
*/
def +=(elem: A): this.type = { self.+=(elem); this }
- override def readOnly = self.readOnly
-
/** Appends a number of elements provided by a traversable object.
*
* @param xs the traversable object.
@@ -132,7 +130,7 @@ trait BufferProxy[A] extends Buffer[A] with Proxy {
*
* @param cmd the message to send.
*/
- @deprecated("Scripting is deprecated.", "2.11.0")
+ @deprecated("scripting is deprecated", "2.11.0")
override def <<(cmd: Message[A]) { self << cmd }
/** Return a clone of this buffer.
diff --git a/src/library/scala/collection/mutable/Builder.scala b/src/library/scala/collection/mutable/Builder.scala
index 75560580cc..528f78bd98 100644
--- a/src/library/scala/collection/mutable/Builder.scala
+++ b/src/library/scala/collection/mutable/Builder.scala
@@ -18,6 +18,14 @@ import generic._
* elements to the builder with `+=` and then converting to the required
* collection type with `result`.
*
+ * One cannot assume that a single `Builder` can build more than one
+ * instance of the desired collection. Particular subclasses may allow
+ * such behavior. Otherwise, `result` should be treated as a terminal
+ * operation: after it is called, no further methods should be called on
+ * the builder. Extend the [[collection.mutable.ReusableBuilder]] trait
+ * instead of `Builder` for builders that may be reused to build multiple
+ * instances.
+ *
* @tparam Elem the type of elements that get added to the builder.
* @tparam To the type of collection that it produced.
*
@@ -36,8 +44,10 @@ trait Builder[-Elem, +To] extends Growable[Elem] {
*/
def clear()
- /** Produces a collection from the added elements.
- * The builder's contents are undefined after this operation.
+ /** Produces a collection from the added elements. This is a terminal operation:
+ * the builder's contents are undefined after this operation, and no further
+ * methods should be called.
+ *
* @return a collection containing the elements added to this builder.
*/
def result(): To
@@ -55,18 +65,18 @@ trait Builder[-Elem, +To] extends Growable[Elem] {
/** Gives a hint that one expects the `result` of this builder
* to have the same size as the given collection, plus some delta. This will
* provide a hint only if the collection is known to have a cheap
- * `size` method. Currently this is assumed to be the case if and only if
- * the collection is of type `IndexedSeqLike`.
- * Some builder classes
- * will optimize their representation based on the hint. However,
+ * `size` method, which is determined by calling `sizeHint`.
+ *
+ * Some builder classes will optimize their representation based on the hint. However,
* builder implementations are still required to work correctly even if the hint is
* wrong, i.e. a different number of elements is added.
*
* @param coll the collection which serves as a hint for the result's size.
*/
def sizeHint(coll: TraversableLike[_, _]) {
- if (coll.isInstanceOf[collection.IndexedSeqLike[_,_]]) {
- sizeHint(coll.size)
+ coll.sizeHintIfCheap match {
+ case -1 =>
+ case n => sizeHint(n)
}
}
@@ -84,8 +94,9 @@ trait Builder[-Elem, +To] extends Growable[Elem] {
* @param delta a correction to add to the `coll.size` to produce the size hint.
*/
def sizeHint(coll: TraversableLike[_, _], delta: Int) {
- if (coll.isInstanceOf[collection.IndexedSeqLike[_,_]]) {
- sizeHint(coll.size + delta)
+ coll.sizeHintIfCheap match {
+ case -1 =>
+ case n => sizeHint(n + delta)
}
}
@@ -102,8 +113,10 @@ trait Builder[-Elem, +To] extends Growable[Elem] {
* than collection's size are reduced.
*/
def sizeHintBounded(size: Int, boundingColl: TraversableLike[_, _]) {
- if (boundingColl.isInstanceOf[collection.IndexedSeqLike[_,_]])
- sizeHint(size min boundingColl.size)
+ boundingColl.sizeHintIfCheap match {
+ case -1 =>
+ case n => sizeHint(size min n)
+ }
}
/** Creates a new builder by applying a transformation function to
@@ -112,6 +125,8 @@ trait Builder[-Elem, +To] extends Growable[Elem] {
* @tparam NewTo the type of collection returned by `f`.
* @return a new builder which is the same as the current builder except
* that a transformation function is applied to this builder's result.
+ *
+ * @note The original builder should no longer be used after `mapResult` is called.
*/
def mapResult[NewTo](f: To => NewTo): Builder[Elem, NewTo] =
new Builder[Elem, NewTo] with Proxy {
diff --git a/src/library/scala/collection/mutable/DefaultMapModel.scala b/src/library/scala/collection/mutable/DefaultMapModel.scala
index 0088620540..7f832c0766 100644
--- a/src/library/scala/collection/mutable/DefaultMapModel.scala
+++ b/src/library/scala/collection/mutable/DefaultMapModel.scala
@@ -19,7 +19,7 @@ package mutable
* @version 1.0, 08/07/2003
* @since 1
*/
-@deprecated("This trait will be removed.", "2.11.0")
+@deprecated("this trait will be removed", "2.11.0")
trait DefaultMapModel[A, B] extends Map[A, B] {
type Entry = DefaultEntry[A, B]
diff --git a/src/library/scala/collection/mutable/DoubleLinkedList.scala b/src/library/scala/collection/mutable/DoubleLinkedList.scala
index fd95e74fbc..537cebd903 100644
--- a/src/library/scala/collection/mutable/DoubleLinkedList.scala
+++ b/src/library/scala/collection/mutable/DoubleLinkedList.scala
@@ -41,7 +41,7 @@ import generic._
* @define mayNotTerminateInf
* @define willNotTerminateInf
*/
-@deprecated("Low-level linked lists are deprecated due to idiosyncrasies in interface and incomplete features.", "2.11.0")
+@deprecated("low-level linked lists are deprecated due to idiosyncrasies in interface and incomplete features", "2.11.0")
@SerialVersionUID(-8144992287952814767L)
class DoubleLinkedList[A]() extends AbstractSeq[A]
with LinearSeq[A]
@@ -78,7 +78,7 @@ class DoubleLinkedList[A]() extends AbstractSeq[A]
* @define coll double linked list
* @define Coll `DoubleLinkedList`
*/
-@deprecated("Low-level linked lists are deprecated.", "2.11.0")
+@deprecated("low-level linked lists are deprecated", "2.11.0")
object DoubleLinkedList extends SeqFactory[DoubleLinkedList] {
/** $genericCanBuildFromInfo */
implicit def canBuildFrom[A]: CanBuildFrom[Coll, A, DoubleLinkedList[A]] = ReusableCBF.asInstanceOf[GenericCanBuildFrom[A]]
diff --git a/src/library/scala/collection/mutable/DoubleLinkedListLike.scala b/src/library/scala/collection/mutable/DoubleLinkedListLike.scala
index aafe34f50a..e85ef05319 100644
--- a/src/library/scala/collection/mutable/DoubleLinkedListLike.scala
+++ b/src/library/scala/collection/mutable/DoubleLinkedListLike.scala
@@ -56,7 +56,7 @@ import scala.annotation.migration
* @define Coll `DoubleLinkedList`
* @define coll double linked list
*/
-@deprecated("Low-level linked lists are deprecated due to idiosyncrasies in interface and incomplete features.", "2.11.0")
+@deprecated("low-level linked lists are deprecated due to idiosyncrasies in interface and incomplete features", "2.11.0")
trait DoubleLinkedListLike[A, This <: Seq[A] with DoubleLinkedListLike[A, This]] extends SeqLike[A, This] with LinkedListLike[A, This] { self =>
/** A reference to the node in the linked list preceding the current node. */
diff --git a/src/library/scala/collection/mutable/FlatHashTable.scala b/src/library/scala/collection/mutable/FlatHashTable.scala
index 8c4115b1dd..0d8799282f 100644
--- a/src/library/scala/collection/mutable/FlatHashTable.scala
+++ b/src/library/scala/collection/mutable/FlatHashTable.scala
@@ -47,9 +47,7 @@ trait FlatHashTable[A] extends FlatHashTable.HashUtils[A] {
@transient protected var seedvalue: Int = tableSizeSeed
- import HashTable.powerOfTwo
-
- protected def capacity(expectedSize: Int) = if (expectedSize == 0) 1 else powerOfTwo(expectedSize)
+ protected def capacity(expectedSize: Int) = HashTable.nextPositivePowerOfTwo(expectedSize)
/** The initial size of the hash table.
*/
diff --git a/src/library/scala/collection/mutable/GrowingBuilder.scala b/src/library/scala/collection/mutable/GrowingBuilder.scala
index c4b5e546aa..27d554d98e 100644
--- a/src/library/scala/collection/mutable/GrowingBuilder.scala
+++ b/src/library/scala/collection/mutable/GrowingBuilder.scala
@@ -15,6 +15,8 @@ import generic._
/** The canonical builder for collections that are growable, i.e. that support an
* efficient `+=` method which adds an element to the collection.
*
+ * GrowableBuilders can produce only a single instance of the collection they are growing.
+ *
* @author Paul Phillips
* @version 2.8
* @since 2.8
@@ -25,6 +27,6 @@ import generic._
class GrowingBuilder[Elem, To <: Growable[Elem]](empty: To) extends Builder[Elem, To] {
protected var elems: To = empty
def +=(x: Elem): this.type = { elems += x; this }
- def clear() { elems = empty }
+ def clear() { empty.clear }
def result: To = elems
}
diff --git a/src/library/scala/collection/mutable/HashMap.scala b/src/library/scala/collection/mutable/HashMap.scala
index 11ff1f0893..de61ebb796 100644
--- a/src/library/scala/collection/mutable/HashMap.scala
+++ b/src/library/scala/collection/mutable/HashMap.scala
@@ -73,10 +73,18 @@ extends AbstractMap[A, B]
}
override def getOrElseUpdate(key: A, defaultValue: => B): B = {
- val i = index(elemHashCode(key))
+ val hash = elemHashCode(key)
+ val i = index(hash)
val entry = findEntry(key, i)
if (entry != null) entry.value
- else addEntry(createNewEntry(key, defaultValue), i)
+ else {
+ val table0 = table
+ val default = defaultValue
+ // Avoid recomputing index if the `defaultValue()` hasn't triggered
+ // a table resize.
+ val newEntryIndex = if (table0 eq table) i else index(hash)
+ addEntry(createNewEntry(key, default), newEntryIndex)
+ }
}
/* inlined HashTable.findEntry0 to preserve its visibility */
diff --git a/src/library/scala/collection/mutable/HashTable.scala b/src/library/scala/collection/mutable/HashTable.scala
index 4873aa3c3e..01ec1defad 100644
--- a/src/library/scala/collection/mutable/HashTable.scala
+++ b/src/library/scala/collection/mutable/HashTable.scala
@@ -367,7 +367,11 @@ trait HashTable[A, Entry >: Null <: HashEntry[A, Entry]] extends HashTable.HashU
* Note: we take the most significant bits of the hashcode, not the lower ones
* this is of crucial importance when populating the table in parallel
*/
- protected final def index(hcode: Int): Int = if (table.length == 1) 0 else improve(hcode, seedvalue) >>> numberOfLeadingZeros(table.length - 1)
+ protected final def index(hcode: Int): Int = {
+ val ones = table.length - 1
+ val exponent = Integer.numberOfLeadingZeros(ones)
+ (improve(hcode, seedvalue) >>> exponent) & ones
+ }
protected def initWithContents(c: HashTable.Contents[A, Entry]) = {
if (c != null) {
@@ -395,13 +399,13 @@ private[collection] object HashTable {
/** The load factor for the hash table (in 0.001 step).
*/
private[collection] final def defaultLoadFactor: Int = 750 // corresponds to 75%
- private[collection] final def loadFactorDenum = 1000
+ private[collection] final def loadFactorDenum = 1000 // should be loadFactorDenom, but changing that isn't binary compatible
private[collection] final def newThreshold(_loadFactor: Int, size: Int) = ((size.toLong * _loadFactor) / loadFactorDenum).toInt
private[collection] final def sizeForThreshold(_loadFactor: Int, thr: Int) = ((thr.toLong * loadFactorDenum) / _loadFactor).toInt
- private[collection] final def capacity(expectedSize: Int) = if (expectedSize == 0) 1 else powerOfTwo(expectedSize)
+ private[collection] final def capacity(expectedSize: Int) = nextPositivePowerOfTwo(expectedSize)
trait HashUtils[KeyType] {
protected final def sizeMapBucketBitSize = 5
@@ -429,16 +433,7 @@ private[collection] object HashTable {
/**
* Returns a power of two >= `target`.
*/
- private[collection] def powerOfTwo(target: Int): Int = {
- /* See http://bits.stephan-brumme.com/roundUpToNextPowerOfTwo.html */
- var c = target - 1
- c |= c >>> 1
- c |= c >>> 2
- c |= c >>> 4
- c |= c >>> 8
- c |= c >>> 16
- c + 1
- }
+ private[collection] def nextPositivePowerOfTwo(target: Int): Int = 1 << -numberOfLeadingZeros(target - 1)
class Contents[A, Entry >: Null <: HashEntry[A, Entry]](
val loadFactor: Int,
diff --git a/src/library/scala/collection/mutable/History.scala b/src/library/scala/collection/mutable/History.scala
index 19148c0ac2..13e2f32225 100644
--- a/src/library/scala/collection/mutable/History.scala
+++ b/src/library/scala/collection/mutable/History.scala
@@ -1,6 +1,6 @@
/* __ *\
** ________ ___ / / ___ Scala API **
-** / __/ __// _ | / / / _ | (c) 2003-2013, LAMP/tPFL **
+** / __/ __// _ | / / / _ | (c) 2003-2013, LAMP/EPFL **
** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ **
** /____/\___/_/ |_/____/_/ | | **
** |/ **
diff --git a/src/library/scala/collection/mutable/ImmutableMapAdaptor.scala b/src/library/scala/collection/mutable/ImmutableMapAdaptor.scala
index 9ece8b1335..7ab4dd2d9d 100644
--- a/src/library/scala/collection/mutable/ImmutableMapAdaptor.scala
+++ b/src/library/scala/collection/mutable/ImmutableMapAdaptor.scala
@@ -25,7 +25,7 @@ import scala.annotation.migration
* @version 2.0, 01/01/2007
* @since 1
*/
-@deprecated("Adaptors are inherently unreliable and prone to performance problems.", "2.11.0")
+@deprecated("adaptors are inherently unreliable and prone to performance problems", "2.11.0")
class ImmutableMapAdaptor[A, B](protected var imap: immutable.Map[A, B])
extends AbstractMap[A, B]
with Map[A, B]
diff --git a/src/library/scala/collection/mutable/ImmutableSetAdaptor.scala b/src/library/scala/collection/mutable/ImmutableSetAdaptor.scala
index d7eec70b15..aa21c4cc11 100644
--- a/src/library/scala/collection/mutable/ImmutableSetAdaptor.scala
+++ b/src/library/scala/collection/mutable/ImmutableSetAdaptor.scala
@@ -20,7 +20,7 @@ package mutable
* @version 1.0, 21/07/2003
* @since 1
*/
-@deprecated("Adaptors are inherently unreliable and prone to performance problems.", "2.11.0")
+@deprecated("adaptors are inherently unreliable and prone to performance problems", "2.11.0")
class ImmutableSetAdaptor[A](protected var set: immutable.Set[A])
extends AbstractSet[A]
with Set[A]
diff --git a/src/library/scala/collection/mutable/IndexedSeqView.scala b/src/library/scala/collection/mutable/IndexedSeqView.scala
index 7acdeeff18..b525baaf5f 100644
--- a/src/library/scala/collection/mutable/IndexedSeqView.scala
+++ b/src/library/scala/collection/mutable/IndexedSeqView.scala
@@ -15,7 +15,6 @@ package mutable
import generic._
import TraversableView.NoBuilder
-import scala.language.implicitConversions
/** A non-strict view of a mutable `IndexedSeq`.
* $viewInfo
diff --git a/src/library/scala/collection/mutable/LazyBuilder.scala b/src/library/scala/collection/mutable/LazyBuilder.scala
index ebee38b77f..f0a5e6971a 100644
--- a/src/library/scala/collection/mutable/LazyBuilder.scala
+++ b/src/library/scala/collection/mutable/LazyBuilder.scala
@@ -13,12 +13,14 @@ package mutable
/** A builder that constructs its result lazily. Iterators or iterables to
* be added to this builder with `++=` are not evaluated until `result` is called.
*
+ * This builder can be reused.
+ *
* @since 2.8
*
* @tparam Elem type of the elements for this builder.
* @tparam To type of the collection this builder builds.
*/
-abstract class LazyBuilder[Elem, +To] extends Builder[Elem, To] {
+abstract class LazyBuilder[Elem, +To] extends ReusableBuilder[Elem, To] {
/** The different segments of elements to be added to the builder, represented as iterators */
protected var parts = new ListBuffer[TraversableOnce[Elem]]
def +=(x: Elem): this.type = { parts += List(x); this }
diff --git a/src/library/scala/collection/mutable/LinkedList.scala b/src/library/scala/collection/mutable/LinkedList.scala
index b3500367af..5d03cd4410 100644
--- a/src/library/scala/collection/mutable/LinkedList.scala
+++ b/src/library/scala/collection/mutable/LinkedList.scala
@@ -76,7 +76,7 @@ import generic._
* }}}
*/
@SerialVersionUID(-7308240733518833071L)
-@deprecated("Low-level linked lists are deprecated due to idiosyncrasies in interface and incomplete features.", "2.11.0")
+@deprecated("low-level linked lists are deprecated due to idiosyncrasies in interface and incomplete features", "2.11.0")
class LinkedList[A]() extends AbstractSeq[A]
with LinearSeq[A]
with GenericTraversableTemplate[A, LinkedList]
@@ -114,7 +114,7 @@ class LinkedList[A]() extends AbstractSeq[A]
* @define Coll `LinkedList`
* @define coll linked list
*/
-@deprecated("Low-level linked lists are deprecated.", "2.11.0")
+@deprecated("low-level linked lists are deprecated", "2.11.0")
object LinkedList extends SeqFactory[LinkedList] {
override def empty[A]: LinkedList[A] = new LinkedList[A]
implicit def canBuildFrom[A]: CanBuildFrom[Coll, A, LinkedList[A]] = ReusableCBF.asInstanceOf[GenericCanBuildFrom[A]]
diff --git a/src/library/scala/collection/mutable/LinkedListLike.scala b/src/library/scala/collection/mutable/LinkedListLike.scala
index d0748b8a9f..27c4466c99 100644
--- a/src/library/scala/collection/mutable/LinkedListLike.scala
+++ b/src/library/scala/collection/mutable/LinkedListLike.scala
@@ -55,7 +55,7 @@ import scala.annotation.tailrec
*
* }}}
*/
-@deprecated("Low-level linked lists are deprecated due to idiosyncrasies in interface and incomplete features.", "2.11.0")
+@deprecated("low-level linked lists are deprecated due to idiosyncrasies in interface and incomplete features", "2.11.0")
trait LinkedListLike[A, This <: Seq[A] with LinkedListLike[A, This]] extends SeqLike[A, This] { self =>
var elem: A = _
diff --git a/src/library/scala/collection/mutable/ListBuffer.scala b/src/library/scala/collection/mutable/ListBuffer.scala
index f9bab40a1e..aa79e972d5 100644
--- a/src/library/scala/collection/mutable/ListBuffer.scala
+++ b/src/library/scala/collection/mutable/ListBuffer.scala
@@ -12,8 +12,7 @@ package mutable
import generic._
import immutable.{List, Nil, ::}
-import java.io._
-import scala.annotation.migration
+import java.io.{ObjectOutputStream, ObjectInputStream}
/** A `Buffer` implementation backed by a list. It provides constant time
* prepend and append. Most other operations are linear.
@@ -47,7 +46,7 @@ final class ListBuffer[A]
with Buffer[A]
with GenericTraversableTemplate[A, ListBuffer]
with BufferLike[A, ListBuffer[A]]
- with Builder[A, List[A]]
+ with ReusableBuilder[A, List[A]]
with SeqForwarder[A]
with Serializable
{
@@ -120,6 +119,10 @@ final class ListBuffer[A]
// Don't use the inherited size, which forwards to a List and is O(n).
override def size = length
+ // Override with efficient implementations using the extra size information available to ListBuffer.
+ override def isEmpty: Boolean = len == 0
+ override def nonEmpty: Boolean = len > 0
+
// Implementations of abstract methods in Buffer
override def apply(n: Int): A =
@@ -262,13 +265,14 @@ final class ListBuffer[A]
*
* @param n the index which refers to the first element to remove.
* @param count the number of elements to remove.
+ * @throws IndexOutOfBoundsException if the index `n` is not in the valid range
+ * `0 <= n <= length - count` (with `count > 0`).
+ * @throws IllegalArgumentException if `count < 0`.
*/
- @migration("Invalid input values will be rejected in future releases.", "2.11")
override def remove(n: Int, count: Int) {
- if (n >= len)
- return
- if (count < 0)
- throw new IllegalArgumentException(s"removing negative number ($count) of elements")
+ if (count < 0) throw new IllegalArgumentException("removing negative number of elements: " + count.toString)
+ else if (count == 0) return // Nothing to do
+ if (n < 0 || n > len - count) throw new IndexOutOfBoundsException("at " + n.toString + " deleting " + count.toString)
if (exported) copy()
val n1 = n max 0
val count1 = count min (len - n1)
@@ -297,6 +301,10 @@ final class ListBuffer[A]
// Implementation of abstract method in Builder
+ /** Returns the accumulated `List`.
+ *
+ * This method may be called multiple times to obtain snapshots of the list in different stages of construction.
+ */
def result: List[A] = toList
/** Converts this buffer to a list. Takes constant time. The buffer is
@@ -382,6 +390,25 @@ final class ListBuffer[A]
this
}
+ /** Selects the last element.
+ *
+ * Runs in constant time.
+ *
+ * @return the last element of this buffer.
+ * @throws NoSuchElementException if this buffer is empty.
+ */
+ override def last: A =
+ if (last0 eq null) throw new NoSuchElementException("last of empty ListBuffer")
+ else last0.head
+
+ /** Optionally selects the last element.
+ *
+ * Runs in constant time.
+ *
+ * @return `Some` of the last element of this buffer if the buffer is nonempty, `None` if it is empty.
+ */
+ override def lastOption: Option[A] = if (last0 eq null) None else Some(last0.head)
+
/** Returns an iterator over this `ListBuffer`. The iterator will reflect
* changes made to the underlying `ListBuffer` beyond the next element;
* the next element's value is cached so that `hasNext` and `next` are
@@ -408,9 +435,6 @@ final class ListBuffer[A]
}
}
- @deprecated("The result of this method will change along with this buffer, which is often not what's expected.", "2.11.0")
- override def readOnly: List[A] = start
-
// Private methods
/** Copy contents of this buffer */
@@ -426,7 +450,7 @@ final class ListBuffer[A]
}
override def equals(that: Any): Boolean = that match {
- case that: ListBuffer[_] => this.readOnly equals that.readOnly
+ case that: ListBuffer[_] => this.start equals that.start
case _ => super.equals(that)
}
diff --git a/src/library/scala/collection/mutable/LongMap.scala b/src/library/scala/collection/mutable/LongMap.scala
index 198e34bd29..ecbb1952af 100644
--- a/src/library/scala/collection/mutable/LongMap.scala
+++ b/src/library/scala/collection/mutable/LongMap.scala
@@ -415,6 +415,24 @@ extends AbstractMap[Long, V]
lm
}
+ override def +[V1 >: V](kv: (Long, V1)): LongMap[V1] = {
+ val lm = clone().asInstanceOf[LongMap[V1]]
+ lm += kv
+ lm
+ }
+
+ override def ++[V1 >: V](xs: GenTraversableOnce[(Long, V1)]): LongMap[V1] = {
+ val lm = clone().asInstanceOf[LongMap[V1]]
+ xs.foreach(kv => lm += kv)
+ lm
+ }
+
+ override def updated[V1 >: V](key: Long, value: V1): LongMap[V1] = {
+ val lm = clone().asInstanceOf[LongMap[V1]]
+ lm += (key, value)
+ lm
+ }
+
/** Applies a function to all keys of this map. */
def foreachKey[A](f: Long => A) {
if ((extraKeys & 1) == 1) f(0L)
@@ -501,7 +519,11 @@ object LongMap {
def apply(): LongMapBuilder[U] = new LongMapBuilder[U]
}
- final class LongMapBuilder[V] extends Builder[(Long, V), LongMap[V]] {
+ /** A builder for instances of `LongMap`.
+ *
+ * This builder can be reused to create multiple instances.
+ */
+ final class LongMapBuilder[V] extends ReusableBuilder[(Long, V), LongMap[V]] {
private[collection] var elems: LongMap[V] = new LongMap[V]
def +=(entry: (Long, V)): this.type = {
elems += entry
@@ -541,7 +563,7 @@ object LongMap {
/** Creates a new `LongMap` from keys and values.
* Equivalent to but more efficient than `LongMap((keys zip values): _*)`.
*/
- def fromZip[V](keys: Iterable[Long], values: Iterable[V]): LongMap[V] = {
+ def fromZip[V](keys: collection.Iterable[Long], values: collection.Iterable[V]): LongMap[V] = {
val sz = math.min(keys.size, values.size)
val lm = new LongMap[V](sz * 2)
val ki = keys.iterator
diff --git a/src/library/scala/collection/mutable/Map.scala b/src/library/scala/collection/mutable/Map.scala
index 2ac3cb65b5..460a8b8f77 100644
--- a/src/library/scala/collection/mutable/Map.scala
+++ b/src/library/scala/collection/mutable/Map.scala
@@ -20,15 +20,15 @@ import generic._
* @since 1.0
* @author Matthias Zenger
*/
-trait Map[A, B]
- extends Iterable[(A, B)]
-// with GenMap[A, B]
- with scala.collection.Map[A, B]
- with MapLike[A, B, Map[A, B]] {
+trait Map[K, V]
+ extends Iterable[(K, V)]
+// with GenMap[K, V]
+ with scala.collection.Map[K, V]
+ with MapLike[K, V, Map[K, V]] {
- override def empty: Map[A, B] = Map.empty
+ override def empty: Map[K, V] = Map.empty
- override def seq: Map[A, B] = this
+ override def seq: Map[K, V] = this
/** The same map with a given default function.
*
@@ -37,7 +37,7 @@ trait Map[A, B]
* @param d the function mapping keys to values, used for non-present keys
* @return a wrapper of the map with a default value
*/
- def withDefault(d: A => B): mutable.Map[A, B] = new Map.WithDefault[A, B](this, d)
+ def withDefault(d: K => V): mutable.Map[K, V] = new Map.WithDefault[K, V](this, d)
/** The same map with a given default value.
*
@@ -46,7 +46,7 @@ trait Map[A, B]
* @param d default value used for non-present keys
* @return a wrapper of the map with a default value
*/
- def withDefaultValue(d: B): mutable.Map[A, B] = new Map.WithDefault[A, B](this, x => d)
+ def withDefaultValue(d: V): mutable.Map[K, V] = new Map.WithDefault[K, V](this, x => d)
}
/** $factoryInfo
@@ -56,25 +56,25 @@ trait Map[A, B]
*/
object Map extends MutableMapFactory[Map] {
/** $canBuildFromInfo */
- implicit def canBuildFrom[A, B]: CanBuildFrom[Coll, (A, B), Map[A, B]] = new MapCanBuildFrom[A, B]
+ implicit def canBuildFrom[K, V]: CanBuildFrom[Coll, (K, V), Map[K, V]] = new MapCanBuildFrom[K, V]
- def empty[A, B]: Map[A, B] = new HashMap[A, B]
+ def empty[K, V]: Map[K, V] = new HashMap[K, V]
- class WithDefault[A, B](underlying: Map[A, B], d: A => B) extends scala.collection.Map.WithDefault(underlying, d) with Map[A, B] {
- override def += (kv: (A, B)) = {underlying += kv; this}
- def -= (key: A) = {underlying -= key; this}
+ class WithDefault[K, V](underlying: Map[K, V], d: K => V) extends scala.collection.Map.WithDefault(underlying, d) with Map[K, V] {
+ override def += (kv: (K, V)) = {underlying += kv; this}
+ def -= (key: K) = {underlying -= key; this}
override def empty = new WithDefault(underlying.empty, d)
- override def updated[B1 >: B](key: A, value: B1): WithDefault[A, B1] = new WithDefault[A, B1](underlying.updated[B1](key, value), d)
- override def + [B1 >: B](kv: (A, B1)): WithDefault[A, B1] = updated(kv._1, kv._2)
- override def - (key: A): WithDefault[A, B] = new WithDefault(underlying - key, d)
+ override def updated[V1 >: V](key: K, value: V1): WithDefault[K, V1] = new WithDefault[K, V1](underlying.updated[V1](key, value), d)
+ override def + [V1 >: V](kv: (K, V1)): WithDefault[K, V1] = updated(kv._1, kv._2)
+ override def - (key: K): WithDefault[K, V] = new WithDefault(underlying - key, d)
/** If these methods aren't overridden to thread through the underlying map,
* successive calls to withDefault* have no effect.
*/
- override def withDefault(d: A => B): mutable.Map[A, B] = new WithDefault[A, B](underlying, d)
- override def withDefaultValue(d: B): mutable.Map[A, B] = new WithDefault[A, B](underlying, x => d)
+ override def withDefault(d: K => V): mutable.Map[K, V] = new WithDefault[K, V](underlying, d)
+ override def withDefaultValue(d: V): mutable.Map[K, V] = new WithDefault[K, V](underlying, x => d)
}
}
/** Explicit instantiation of the `Map` trait to reduce class file size in subclasses. */
-abstract class AbstractMap[A, B] extends scala.collection.AbstractMap[A, B] with Map[A, B]
+abstract class AbstractMap[K, V] extends scala.collection.AbstractMap[K, V] with Map[K, V]
diff --git a/src/library/scala/collection/mutable/MapBuilder.scala b/src/library/scala/collection/mutable/MapBuilder.scala
index a5a6b12ea9..cfc3079f41 100644
--- a/src/library/scala/collection/mutable/MapBuilder.scala
+++ b/src/library/scala/collection/mutable/MapBuilder.scala
@@ -23,7 +23,7 @@ package mutable
* @since 2.8
*/
class MapBuilder[A, B, Coll <: scala.collection.GenMap[A, B] with scala.collection.GenMapLike[A, B, Coll]](empty: Coll)
-extends Builder[(A, B), Coll] {
+extends ReusableBuilder[(A, B), Coll] {
protected var elems: Coll = empty
def +=(x: (A, B)): this.type = {
elems = (elems + x).asInstanceOf[Coll]
diff --git a/src/library/scala/collection/mutable/MapLike.scala b/src/library/scala/collection/mutable/MapLike.scala
index 44af886cf5..238b6d1be1 100644
--- a/src/library/scala/collection/mutable/MapLike.scala
+++ b/src/library/scala/collection/mutable/MapLike.scala
@@ -31,10 +31,10 @@ import scala.collection.parallel.mutable.ParMap
* To implement a concrete mutable map, you need to provide
* implementations of the following methods:
* {{{
- * def get(key: A): Option[B]
- * def iterator: Iterator[(A, B)]
- * def += (kv: (A, B)): This
- * def -= (key: A): This
+ * def get(key: K): Option[V]
+ * def iterator: Iterator[(K, V)]
+ * def += (kv: (K, V)): This
+ * def -= (key: K): This
* }}}
* If you wish that methods like `take`, `drop`, `filter` also return the same kind of map
* you should also override:
@@ -44,13 +44,13 @@ import scala.collection.parallel.mutable.ParMap
* It is also good idea to override methods `foreach` and
* `size` for efficiency.
*/
-trait MapLike[A, B, +This <: MapLike[A, B, This] with Map[A, B]]
- extends scala.collection.MapLike[A, B, This]
- with Builder[(A, B), This]
- with Growable[(A, B)]
- with Shrinkable[A]
+trait MapLike[K, V, +This <: MapLike[K, V, This] with Map[K, V]]
+ extends scala.collection.MapLike[K, V, This]
+ with Builder[(K, V), This]
+ with Growable[(K, V)]
+ with Shrinkable[K]
with Cloneable[This]
- with Parallelizable[(A, B), ParMap[A, B]]
+ with Parallelizable[(K, V), ParMap[K, V]]
{ self =>
/** A common implementation of `newBuilder` for all mutable maps
@@ -58,9 +58,21 @@ trait MapLike[A, B, +This <: MapLike[A, B, This] with Map[A, B]]
*
* Overrides `MapLike` implementation for better efficiency.
*/
- override protected[this] def newBuilder: Builder[(A, B), This] = empty
+ override protected[this] def newBuilder: Builder[(K, V), This] = empty
+
+ protected[this] override def parCombiner = ParMap.newCombiner[K, V]
+
+ /** Converts this $coll to a sequence.
+ *
+ * ```Note```: assumes a fast `size` method. Subclasses should override if this is not true.
+ */
+ override def toSeq: collection.Seq[(K, V)] = {
+ // ArrayBuffer for efficiency, preallocated to the right size.
+ val result = new ArrayBuffer[(K, V)](size)
+ foreach(result += _)
+ result
+ }
- protected[this] override def parCombiner = ParMap.newCombiner[A, B]
/** Adds a new key/value pair to this map and optionally returns previously bound value.
* If the map already contains a
@@ -72,7 +84,7 @@ trait MapLike[A, B, +This <: MapLike[A, B, This] with Map[A, B]]
* before the `put` operation was executed, or `None` if `key`
* was not defined in the map before.
*/
- def put(key: A, value: B): Option[B] = {
+ def put(key: K, value: V): Option[V] = {
val r = get(key)
update(key, value)
r
@@ -85,7 +97,7 @@ trait MapLike[A, B, +This <: MapLike[A, B, This] with Map[A, B]]
* @param key The key to update
* @param value The new value
*/
- def update(key: A, value: B) { this += ((key, value)) }
+ def update(key: K, value: V) { this += ((key, value)) }
/** Adds a new key/value pair to this map.
* If the map already contains a
@@ -93,7 +105,7 @@ trait MapLike[A, B, +This <: MapLike[A, B, This] with Map[A, B]]
* @param kv the key/value pair.
* @return the map itself
*/
- def += (kv: (A, B)): this.type
+ def += (kv: (K, V)): this.type
/** Creates a new map consisting of all key/value pairs of the current map
* plus a new pair of a given key and value.
@@ -103,7 +115,7 @@ trait MapLike[A, B, +This <: MapLike[A, B, This] with Map[A, B]]
* @return A fresh immutable map with the binding from `key` to
* `value` added to this map.
*/
- override def updated[B1 >: B](key: A, value: B1): Map[A, B1] = this + ((key, value))
+ override def updated[V1 >: V](key: K, value: V1): Map[K, V1] = this + ((key, value))
/** Creates a new map containing a new key/value mapping and all the key/value mappings
* of this map.
@@ -114,7 +126,7 @@ trait MapLike[A, B, +This <: MapLike[A, B, This] with Map[A, B]]
* @return a new map containing mappings of this map and the mapping `kv`.
*/
@migration("`+` creates a new map. Use `+=` to add an element to this map and return that map itself.", "2.8.0")
- def + [B1 >: B] (kv: (A, B1)): Map[A, B1] = clone().asInstanceOf[Map[A, B1]] += kv
+ def + [V1 >: V] (kv: (K, V1)): Map[K, V1] = clone().asInstanceOf[Map[K, V1]] += kv
/** Creates a new map containing two or more key/value mappings and all the key/value
* mappings of this map.
@@ -127,8 +139,8 @@ trait MapLike[A, B, +This <: MapLike[A, B, This] with Map[A, B]]
* @return a new map containing mappings of this map and two or more specified mappings.
*/
@migration("`+` creates a new map. Use `+=` to add an element to this map and return that map itself.", "2.8.0")
- override def + [B1 >: B] (elem1: (A, B1), elem2: (A, B1), elems: (A, B1) *): Map[A, B1] =
- clone().asInstanceOf[Map[A, B1]] += elem1 += elem2 ++= elems
+ override def + [V1 >: V] (elem1: (K, V1), elem2: (K, V1), elems: (K, V1) *): Map[K, V1] =
+ clone().asInstanceOf[Map[K, V1]] += elem1 += elem2 ++= elems
/** Creates a new map containing the key/value mappings provided by the specified traversable object
* and all the key/value mappings of this map.
@@ -139,8 +151,8 @@ trait MapLike[A, B, +This <: MapLike[A, B, This] with Map[A, B]]
* @return a new map containing mappings of this map and those provided by `xs`.
*/
@migration("`++` creates a new map. Use `++=` to add an element to this map and return that map itself.", "2.8.0")
- override def ++[B1 >: B](xs: GenTraversableOnce[(A, B1)]): Map[A, B1] =
- clone().asInstanceOf[Map[A, B1]] ++= xs.seq
+ override def ++[V1 >: V](xs: GenTraversableOnce[(K, V1)]): Map[K, V1] =
+ clone().asInstanceOf[Map[K, V1]] ++= xs.seq
/** Removes a key from this map, returning the value associated previously
* with that key as an option.
@@ -148,7 +160,7 @@ trait MapLike[A, B, +This <: MapLike[A, B, This] with Map[A, B]]
* @return an option value containing the value associated previously with `key`,
* or `None` if `key` was not defined in the map before.
*/
- def remove(key: A): Option[B] = {
+ def remove(key: K): Option[V] = {
val r = get(key)
this -= key
r
@@ -158,7 +170,7 @@ trait MapLike[A, B, +This <: MapLike[A, B, This] with Map[A, B]]
* @param key the key to be removed
* @return the map itself.
*/
- def -= (key: A): this.type
+ def -= (key: K): this.type
/** Creates a new map with all the key/value mappings of this map except the key/value mapping
* with the specified key.
@@ -167,7 +179,7 @@ trait MapLike[A, B, +This <: MapLike[A, B, This] with Map[A, B]]
* @return a new map with all the mappings of this map except that with a key `key`.
*/
@migration("`-` creates a new map. Use `-=` to remove an element from this map and return that map itself.", "2.8.0")
- override def -(key: A): This = clone() -= key
+ override def -(key: K): This = clone() -= key
/** Removes all bindings from the map. After this operation has completed,
* the map will be empty.
@@ -188,7 +200,7 @@ trait MapLike[A, B, +This <: MapLike[A, B, This] with Map[A, B]]
* @return the value associated with key (either previously or as a result
* of executing the method).
*/
- def getOrElseUpdate(key: A, op: => B): B =
+ def getOrElseUpdate(key: K, op: => V): V =
get(key) match {
case Some(v) => v
case None => val d = op; this(key) = d; d
@@ -201,7 +213,7 @@ trait MapLike[A, B, +This <: MapLike[A, B, This] with Map[A, B]]
* @param f the transformation to apply
* @return the map itself.
*/
- def transform(f: (A, B) => B): this.type = {
+ def transform(f: (K, V) => V): this.type = {
this.iterator foreach {
case (key, value) => update(key, f(key, value))
}
@@ -213,7 +225,7 @@ trait MapLike[A, B, +This <: MapLike[A, B, This] with Map[A, B]]
*
* @param p The test predicate
*/
- def retain(p: (A, B) => Boolean): this.type = {
+ def retain(p: (K, V) => Boolean): this.type = {
for ((k, v) <- this.toList) // SI-7269 toList avoids ConcurrentModificationException
if (!p(k, v)) this -= k
@@ -237,7 +249,7 @@ trait MapLike[A, B, +This <: MapLike[A, B, This] with Map[A, B]]
* with a key equal to `elem1`, `elem2` or any of `elems`.
*/
@migration("`-` creates a new map. Use `-=` to remove an element from this map and return that map itself.", "2.8.0")
- override def -(elem1: A, elem2: A, elems: A*): This =
+ override def -(elem1: K, elem2: K, elems: K*): This =
clone() -= elem1 -= elem2 --= elems
/** Creates a new map with all the key/value mappings of this map except mappings with keys
@@ -248,5 +260,5 @@ trait MapLike[A, B, +This <: MapLike[A, B, This] with Map[A, B]]
* with a key equal to a key from `xs`.
*/
@migration("`--` creates a new map. Use `--=` to remove an element from this map and return that map itself.", "2.8.0")
- override def --(xs: GenTraversableOnce[A]): This = clone() --= xs.seq
+ override def --(xs: GenTraversableOnce[K]): This = clone() --= xs.seq
}
diff --git a/src/library/scala/collection/mutable/MapProxy.scala b/src/library/scala/collection/mutable/MapProxy.scala
index 552cd9769b..63b14d328a 100644
--- a/src/library/scala/collection/mutable/MapProxy.scala
+++ b/src/library/scala/collection/mutable/MapProxy.scala
@@ -20,7 +20,7 @@ package mutable
* @version 2.0, 31/12/2006
* @since 1
*/
-@deprecated("Proxying is deprecated due to lack of use and compiler-level support.", "2.11.0")
+@deprecated("proxying is deprecated due to lack of use and compiler-level support", "2.11.0")
trait MapProxy[A, B] extends Map[A, B] with MapProxyLike[A, B, Map[A, B]] {
private def newProxy[B1 >: B](newSelf: Map[A, B1]): MapProxy[A, B1] =
new MapProxy[A, B1] { val self = newSelf }
diff --git a/src/library/scala/collection/mutable/MutableList.scala b/src/library/scala/collection/mutable/MutableList.scala
index 646023f469..a333eedb1a 100644
--- a/src/library/scala/collection/mutable/MutableList.scala
+++ b/src/library/scala/collection/mutable/MutableList.scala
@@ -11,7 +11,7 @@ package collection
package mutable
import generic._
-import immutable.{List, Nil}
+import immutable.List
/**
* This class is used internally to represent mutable lists. It is the
diff --git a/src/library/scala/collection/mutable/ObservableBuffer.scala b/src/library/scala/collection/mutable/ObservableBuffer.scala
index 9c3247f83b..53d26f4c6f 100644
--- a/src/library/scala/collection/mutable/ObservableBuffer.scala
+++ b/src/library/scala/collection/mutable/ObservableBuffer.scala
@@ -23,9 +23,8 @@ import script._
* @version 1.0, 08/07/2003
* @since 1
*/
-@deprecated("Observables are deprecated because scripting is deprecated.", "2.11.0")
-trait ObservableBuffer[A] extends Buffer[A] with Publisher[Message[A] with Undoable]
-{
+@deprecated("observables are deprecated because scripting is deprecated", "2.11.0")
+trait ObservableBuffer[A] extends Buffer[A] with Publisher[Message[A] with Undoable] {
type Pub <: ObservableBuffer[A]
abstract override def +=(element: A): this.type = {
diff --git a/src/library/scala/collection/mutable/ObservableMap.scala b/src/library/scala/collection/mutable/ObservableMap.scala
index 7509b72568..421302b700 100644
--- a/src/library/scala/collection/mutable/ObservableMap.scala
+++ b/src/library/scala/collection/mutable/ObservableMap.scala
@@ -25,9 +25,8 @@ import script._
* @version 2.0, 31/12/2006
* @since 1
*/
-@deprecated("Observables are deprecated because scripting is deprecated.", "2.11.0")
-trait ObservableMap[A, B] extends Map[A, B] with Publisher[Message[(A, B)] with Undoable]
-{
+@deprecated("observables are deprecated because scripting is deprecated", "2.11.0")
+trait ObservableMap[A, B] extends Map[A, B] with Publisher[Message[(A, B)] with Undoable] {
type Pub <: ObservableMap[A, B]
diff --git a/src/library/scala/collection/mutable/ObservableSet.scala b/src/library/scala/collection/mutable/ObservableSet.scala
index 19b4a5e39f..eb55a1f822 100644
--- a/src/library/scala/collection/mutable/ObservableSet.scala
+++ b/src/library/scala/collection/mutable/ObservableSet.scala
@@ -23,9 +23,8 @@ import script._
* @version 1.0, 08/07/2003
* @since 1
*/
-@deprecated("Observables are deprecated because scripting is deprecated.", "2.11.0")
-trait ObservableSet[A] extends Set[A] with Publisher[Message[A] with Undoable]
-{
+@deprecated("observables are deprecated because scripting is deprecated", "2.11.0")
+trait ObservableSet[A] extends Set[A] with Publisher[Message[A] with Undoable] {
type Pub <: ObservableSet[A]
diff --git a/src/library/scala/collection/mutable/OpenHashMap.scala b/src/library/scala/collection/mutable/OpenHashMap.scala
index c86357efad..b2e9ee27b9 100644
--- a/src/library/scala/collection/mutable/OpenHashMap.scala
+++ b/src/library/scala/collection/mutable/OpenHashMap.scala
@@ -21,12 +21,16 @@ object OpenHashMap {
def apply[K, V](elems : (K, V)*) = new OpenHashMap[K, V] ++= elems
def empty[K, V] = new OpenHashMap[K, V]
- final private class OpenEntry[Key, Value](val key: Key,
- val hash: Int,
+ /** A hash table entry.
+ *
+ * The entry is occupied if and only if its `value` is a `Some`;
+ * deleted if and only if its `value` is `None`.
+ * If its `key` is not the default value of type `Key`, the entry is occupied.
+ * If the entry is occupied, `hash` contains the hash value of `key`.
+ */
+ final private class OpenEntry[Key, Value](var key: Key,
+ var hash: Int,
var value: Option[Value])
- extends HashEntry[Key, OpenEntry[Key, Value]]
-
- private[mutable] def nextPositivePowerOfTwo(i : Int) = 1 << (32 - Integer.numberOfLeadingZeros(i - 1))
}
/** A mutable hash map based on an open hashing scheme. The precise scheme is
@@ -61,10 +65,17 @@ extends AbstractMap[Key, Value]
override def empty: OpenHashMap[Key, Value] = OpenHashMap.empty[Key, Value]
- private[this] val actualInitialSize = OpenHashMap.nextPositivePowerOfTwo(initialSize)
+ private[this] val actualInitialSize = HashTable.nextPositivePowerOfTwo(initialSize)
private var mask = actualInitialSize - 1
- private var table : Array[Entry] = new Array[Entry](actualInitialSize)
+
+ /** The hash table.
+ *
+ * The table's entries are initialized to `null`, indication of an empty slot.
+ * A slot is either deleted or occupied if and only if the entry is non-`null`.
+ */
+ private[this] var table = new Array[Entry](actualInitialSize)
+
private var _size = 0
private var deleted = 0
@@ -91,39 +102,41 @@ extends AbstractMap[Key, Value]
table = new Array[Entry](newSize)
mask = newSize - 1
oldTable.foreach( entry =>
- if (entry != null && entry.value != None) addEntry(entry))
+ if (entry != null && entry.value != None)
+ table(findIndex(entry.key, entry.hash)) = entry )
deleted = 0
}
/** Return the index of the first slot in the hash table (in probe order)
- * that either is empty, or is or was last occupied by the given key.
- */
- private[this] def findIndex(key: Key) : Int = findIndex(key, hashOf(key))
-
- /** Return the index of the first slot in the hash table (in probe order)
- * that either is empty, or is or was last occupied by the given key.
- *
- * This method is an optimization for when the hash value is in hand.
+ * that is, in order of preference, either occupied by the given key, deleted, or empty.
*
* @param hash hash value for `key`
*/
private[this] def findIndex(key: Key, hash: Int): Int = {
var index = hash & mask
var j = 0
- while(table(index) != null &&
- !(table(index).hash == hash &&
- table(index).key == key)){
+
+ /** Index of the first slot containing a deleted entry, or -1 if none found yet. */
+ var firstDeletedIndex = -1
+
+ var entry = table(index)
+ while (entry != null) {
+ if (entry.hash == hash && entry.key == key && entry.value != None)
+ return index
+
+ if (firstDeletedIndex == -1 && entry.value == None)
+ firstDeletedIndex = index
+
j += 1
index = (index + j) & mask
+ entry = table(index)
}
- index
- }
- private[this] def addEntry(entry: Entry) =
- if (entry != null) table(findIndex(entry.key, entry.hash)) = entry
+ if (firstDeletedIndex == -1) index else firstDeletedIndex
+ }
override def update(key: Key, value: Value) {
- put(key, hashOf(key), value)
+ put(key, value)
}
@deprecatedOverriding("+= should not be overridden in order to maintain consistency with put.", "2.11.0")
@@ -147,6 +160,8 @@ extends AbstractMap[Key, Value]
} else {
val res = entry.value
if (entry.value == None) {
+ entry.key = key
+ entry.hash = hash
size += 1
deleted -= 1
modCount += 1
@@ -156,13 +171,22 @@ extends AbstractMap[Key, Value]
}
}
+ /** Delete the hash table slot contained in the given entry. */
+ @inline
+ private[this] def deleteSlot(entry: Entry) = {
+ entry.key = null.asInstanceOf[Key]
+ entry.hash = 0
+ entry.value = None
+
+ size -= 1
+ deleted += 1
+ }
+
override def remove(key : Key): Option[Value] = {
- val index = findIndex(key)
- if (table(index) != null && table(index).value != None){
- val res = table(index).value
- table(index).value = None
- size -= 1
- deleted += 1
+ val entry = table(findIndex(key, hashOf(key)))
+ if (entry != null && entry.value != None) {
+ val res = entry.value
+ deleteSlot(entry)
res
} else None
}
@@ -243,7 +267,7 @@ extends AbstractMap[Key, Value]
}
override def retain(f : (Key, Value) => Boolean) = {
- foreachUndeletedEntry(entry => if (!f(entry.key, entry.value.get)) {entry.value = None; size -= 1; deleted += 1} )
+ foreachUndeletedEntry(entry => if (!f(entry.key, entry.value.get)) deleteSlot(entry))
this
}
diff --git a/src/library/scala/collection/mutable/PriorityQueue.scala b/src/library/scala/collection/mutable/PriorityQueue.scala
index 2562f60355..ed43ef6db9 100644
--- a/src/library/scala/collection/mutable/PriorityQueue.scala
+++ b/src/library/scala/collection/mutable/PriorityQueue.scala
@@ -16,7 +16,7 @@ import generic._
* To prioritize elements of type A there must be an implicit
* Ordering[A] available at creation.
*
- * Only the `dequeue` and `dequeueAll` methods will return methods in priority
+ * Only the `dequeue` and `dequeueAll` methods will return elements in priority
* order (while removing elements from the heap). Standard collection methods
* including `drop`, `iterator`, and `toString` will remove or traverse the heap
* in whichever order seems most convenient.
@@ -46,8 +46,7 @@ import generic._
* @define mayNotTerminateInf
* @define willNotTerminateInf
*/
-@deprecatedInheritance("PriorityQueue is not intended to be subclassed due to extensive private implementation details.", "2.11.0")
-class PriorityQueue[A](implicit val ord: Ordering[A])
+sealed class PriorityQueue[A](implicit val ord: Ordering[A])
extends AbstractIterable[A]
with Iterable[A]
with GenericOrderedTraversableTemplate[A, PriorityQueue]
@@ -67,7 +66,7 @@ class PriorityQueue[A](implicit val ord: Ordering[A])
def p_swap(a: Int, b: Int) = super.swap(a, b)
}
- protected[this] override def newBuilder = new PriorityQueue[A]
+ protected[this] override def newBuilder = PriorityQueue.newBuilder[A]
private val resarr = new ResizableArrayAccess[A]
@@ -90,14 +89,15 @@ class PriorityQueue[A](implicit val ord: Ordering[A])
}
}
- protected def fixDown(as: Array[AnyRef], m: Int, n: Int): Unit = {
+ protected def fixDown(as: Array[AnyRef], m: Int, n: Int): Boolean = {
+ // returns true if any swaps were done (used in heapify)
var k: Int = m
while (n >= 2 * k) {
var j = 2 * k
if (j < n && toA(as(j)) < toA(as(j + 1)))
j += 1
if (toA(as(k)) >= toA(as(j)))
- return
+ return k != m
else {
val h = as(k)
as(k) = as(j)
@@ -105,6 +105,7 @@ class PriorityQueue[A](implicit val ord: Ordering[A])
k = j
}
}
+ k != m
}
/** Inserts a single element into the priority queue.
@@ -120,6 +121,66 @@ class PriorityQueue[A](implicit val ord: Ordering[A])
this
}
+ override def ++=(xs: TraversableOnce[A]): this.type = {
+ val from = resarr.p_size0
+ for (x <- xs) unsafeAdd(x)
+ heapify(from)
+ this
+ }
+
+ private def unsafeAdd(elem: A): Unit = {
+ // like += but skips fixUp, which breaks the ordering invariant
+ // a series of unsafeAdds MUST be followed by heapify
+ resarr.p_ensureSize(resarr.p_size0 + 1)
+ resarr.p_array(resarr.p_size0) = elem.asInstanceOf[AnyRef]
+ resarr.p_size0 += 1
+ }
+
+ private def heapify(from: Int): Unit = {
+ // elements at indices 1..from-1 were already in heap order before any adds
+ // elements at indices from..n are newly added, their order must be fixed
+ val n = length
+
+ if (from <= 2) {
+ // no pre-existing order to maintain, do the textbook heapify algorithm
+ for (i <- n/2 to 1 by -1) fixDown(resarr.p_array, i, n)
+ }
+ else if (n - from < 4) {
+ // for very small adds, doing the simplest fix is faster
+ for (i <- from to n) fixUp(resarr.p_array, i)
+ }
+ else {
+ var min = from/2 // tracks the minimum element in the queue
+ val queue = scala.collection.mutable.Queue[Int](min)
+
+ // do fixDown on the parents of all the new elements
+ // except the parent of the first new element, which is in the queue
+ // (that parent is treated specially because it might be the root)
+ for (i <- n/2 until min by -1) {
+ if (fixDown(resarr.p_array, i, n)) {
+ // there was a swap, so also need to fixDown i's parent
+ val parent = i/2
+ if (parent < min) { // make sure same parent isn't added twice
+ min = parent
+ queue += parent
+ }
+ }
+ }
+
+ while (queue.nonEmpty) {
+ val i = queue.dequeue()
+ if (fixDown(resarr.p_array, i, n)) {
+ val parent = i/2
+ if (parent < min && parent > 0) {
+ // the "parent > 0" is to avoid adding the parent of the root
+ min = parent
+ queue += parent
+ }
+ }
+ }
+ }
+ }
+
/** Adds all elements provided by a `TraversableOnce` object
* into the priority queue.
*
@@ -143,9 +204,11 @@ class PriorityQueue[A](implicit val ord: Ordering[A])
def dequeue(): A =
if (resarr.p_size0 > 1) {
resarr.p_size0 = resarr.p_size0 - 1
- resarr.p_swap(1, resarr.p_size0)
+ val result = resarr.p_array(1)
+ resarr.p_array(1) = resarr.p_array(resarr.p_size0)
+ resarr.p_array(resarr.p_size0) = null // erase reference from array
fixDown(resarr.p_array, 1, resarr.p_size0 - 1)
- toA(resarr.p_array(resarr.p_size0))
+ toA(result)
} else
throw new NoSuchElementException("no element to remove from heap")
@@ -187,27 +250,34 @@ class PriorityQueue[A](implicit val ord: Ordering[A])
}
}
- /** Returns the reverse of this queue. The priority queue that gets
- * returned will have an inversed ordering - if for some elements
- * `x` and `y` the original queue's ordering
- * had `compare` returning an integer ''w'', the new one will return ''-w'',
- * assuming the original ordering abides its contract.
+ /** Returns the reverse of this priority queue. The new priority queue has
+ * the same elements as the original, but the opposite ordering.
*
- * Note that the order of the elements will be reversed unless the
- * `compare` method returns 0. In this case, such elements
- * will be subsequent, but their corresponding subinterval may be inappropriately
- * reversed. However, due to the compare-equals contract, they will also be equal.
+ * For example, the element with the highest priority in `pq` has the lowest
+ * priority in `pq.reverse`, and vice versa.
*
- * @return A reversed priority queue.
+ * Ties are handled arbitrarily. Elements with equal priority may or
+ * may not be reversed with respect to each other.
+ *
+ * @return the reversed priority queue.
*/
def reverse = {
- val revq = new PriorityQueue[A]()(new scala.math.Ordering[A] {
- def compare(x: A, y: A) = ord.compare(y, x)
- })
- for (i <- 1 until resarr.length) revq += resarr(i)
+ val revq = new PriorityQueue[A]()(ord.reverse)
+ // copy the existing data into the new array backwards
+ // this won't put it exactly into the correct order,
+ // but will require less fixing than copying it in
+ // the original order
+ val n = resarr.p_size0
+ revq.resarr.p_ensureSize(n)
+ revq.resarr.p_size0 = n
+ val from = resarr.p_array
+ val to = revq.resarr.p_array
+ for (i <- 1 until n) to(i) = from(n-i)
+ revq.heapify(1)
revq
}
+
/** Returns an iterator which yields all the elements in the reverse order
* than that returned by the method `iterator`.
*
@@ -257,12 +327,198 @@ class PriorityQueue[A](implicit val ord: Ordering[A])
*
* @return a priority queue with the same elements.
*/
- override def clone(): PriorityQueue[A] = new PriorityQueue[A] ++= this.iterator
+ override def clone(): PriorityQueue[A] = {
+ val pq = new PriorityQueue[A]
+ val n = resarr.p_size0
+ pq.resarr.p_ensureSize(n)
+ java.lang.System.arraycopy(resarr.p_array, 1, pq.resarr.p_array, 1, n-1)
+ pq.resarr.p_size0 = n
+ pq
+ }
}
object PriorityQueue extends OrderedTraversableFactory[PriorityQueue] {
- def newBuilder[A](implicit ord: Ordering[A]) = new PriorityQueue[A]
+ def newBuilder[A](implicit ord: Ordering[A]): Builder[A, PriorityQueue[A]] = {
+ new Builder[A, PriorityQueue[A]] {
+ val pq = new PriorityQueue[A]
+ def +=(elem: A): this.type = { pq.unsafeAdd(elem); this }
+ def result(): PriorityQueue[A] = { pq.heapify(1); pq }
+ def clear(): Unit = pq.clear()
+ }
+ }
+
implicit def canBuildFrom[A](implicit ord: Ordering[A]): CanBuildFrom[Coll, A, PriorityQueue[A]] = new GenericCanBuildFrom[A]
}
+
+/** This class servers as a proxy for priority queues. The
+ * elements of the queue have to be ordered in terms of the
+ * `Ordered[T]` class.
+ *
+ * @author Matthias Zenger
+ * @version 1.0, 03/05/2004
+ * @since 1
+ */
+@deprecated("proxying is deprecated due to lack of use and compiler-level support", "2.11.0")
+sealed abstract class PriorityQueueProxy[A](implicit ord: Ordering[A]) extends PriorityQueue[A] with Proxy {
+ def self: PriorityQueue[A]
+
+ /** Creates a new iterator over all elements contained in this
+ * object.
+ *
+ * @return the new iterator
+ */
+ override def iterator: Iterator[A] = self.iterator
+
+ /** Returns the length of this priority queue.
+ */
+ override def length: Int = self.length
+
+ /** Checks if the queue is empty.
+ *
+ * @return true, iff there is no element in the queue.
+ */
+ override def isEmpty: Boolean = self.isEmpty
+
+ /** Inserts a single element into the priority queue.
+ *
+ * @param elem the element to insert
+ */
+ override def +=(elem: A): this.type = { self += elem; this }
+
+ /** Adds all elements provided by an iterator into the priority queue.
+ *
+ * @param it an iterator
+ */
+ override def ++=(it: TraversableOnce[A]): this.type = {
+ self ++= it
+ this
+ }
+
+ /** Adds all elements to the queue.
+ *
+ * @param elems the elements to add.
+ */
+ override def enqueue(elems: A*): Unit = self ++= elems
+
+ /** Returns the element with the highest priority in the queue,
+ * and removes this element from the queue.
+ *
+ * @return the element with the highest priority.
+ */
+ override def dequeue(): A = self.dequeue()
+
+ /** Returns the element with the highest priority in the queue,
+ * or throws an error if there is no element contained in the queue.
+ *
+ * @return the element with the highest priority.
+ */
+ override def head: A = self.head
+
+ /** Removes all elements from the queue. After this operation is completed,
+ * the queue will be empty.
+ */
+ override def clear(): Unit = self.clear()
+
+ /** Returns a regular queue containing the same elements.
+ */
+ override def toQueue: Queue[A] = self.toQueue
+
+ /** This method clones the priority queue.
+ *
+ * @return a priority queue with the same elements.
+ */
+ override def clone(): PriorityQueue[A] = new PriorityQueueProxy[A] {
+ def self = PriorityQueueProxy.this.self.clone()
+ }
+}
+
+
+/** This class implements synchronized priority queues using a binary heap.
+ * The elements of the queue have to be ordered in terms of the `Ordered[T]` class.
+ *
+ * @tparam A type of the elements contained in this synchronized priority queue
+ * @param ord implicit ordering used to compared elements of type `A`
+ *
+ * @author Matthias Zenger
+ * @version 1.0, 03/05/2004
+ * @since 1
+ * @define Coll `SynchronizedPriorityQueue`
+ * @define coll synchronized priority queue
+ */
+@deprecated("Comprehensive synchronization via selective overriding of methods is inherently unreliable. Consider java.util.concurrent.ConcurrentSkipListSet as an alternative.", "2.11.0")
+sealed class SynchronizedPriorityQueue[A](implicit ord: Ordering[A]) extends PriorityQueue[A] {
+
+ /** Checks if the queue is empty.
+ *
+ * @return true, iff there is no element in the queue.
+ */
+ override def isEmpty: Boolean = synchronized { super.isEmpty }
+
+ /** Inserts a single element into the priority queue.
+ *
+ * @param elem the element to insert
+ */
+ override def +=(elem: A): this.type = {
+ synchronized {
+ super.+=(elem)
+ }
+ this
+ }
+
+ /** Adds all elements of a traversable object into the priority queue.
+ *
+ * @param xs a traversable object
+ */
+ override def ++=(xs: TraversableOnce[A]): this.type = {
+ synchronized {
+ super.++=(xs)
+ }
+ this
+ }
+
+ /** Adds all elements to the queue.
+ *
+ * @param elems the elements to add.
+ */
+ override def enqueue(elems: A*): Unit = synchronized { super.++=(elems) }
+
+ /** Returns the element with the highest priority in the queue,
+ * and removes this element from the queue.
+ *
+ * @return the element with the highest priority.
+ */
+ override def dequeue(): A = synchronized { super.dequeue() }
+
+ /** Returns the element with the highest priority in the queue,
+ * or throws an error if there is no element contained in the queue.
+ *
+ * @return the element with the highest priority.
+ */
+ override def head: A = synchronized { super.head }
+
+ /** Removes all elements from the queue. After this operation is completed,
+ * the queue will be empty.
+ */
+ override def clear(): Unit = synchronized { super.clear() }
+
+ /** Returns an iterator which yield all the elements of the priority
+ * queue in descending priority order.
+ *
+ * @return an iterator over all elements sorted in descending order.
+ */
+ override def iterator: Iterator[A] = synchronized { super.iterator }
+
+ /** Checks if two queues are structurally identical.
+ *
+ * @return true, iff both queues contain the same sequence of elements.
+ */
+ override def equals(that: Any): Boolean = synchronized { super.equals(that) }
+
+ /** Returns a textual representation of a queue as a string.
+ *
+ * @return the string representation of this queue.
+ */
+ override def toString(): String = synchronized { super.toString() }
+}
diff --git a/src/library/scala/collection/mutable/PriorityQueueProxy.scala b/src/library/scala/collection/mutable/PriorityQueueProxy.scala
deleted file mode 100644
index b24551a6b7..0000000000
--- a/src/library/scala/collection/mutable/PriorityQueueProxy.scala
+++ /dev/null
@@ -1,96 +0,0 @@
-/* __ *\
-** ________ ___ / / ___ Scala API **
-** / __/ __// _ | / / / _ | (c) 2003-2013, LAMP/EPFL **
-** __\ \/ /__/ __ |/ /__/ __ | **
-** /____/\___/_/ |_/____/_/ | | **
-** |/ **
-\* */
-
-
-package scala
-package collection
-package mutable
-
-/** This class servers as a proxy for priority queues. The
- * elements of the queue have to be ordered in terms of the
- * `Ordered[T]` class.
- *
- * @author Matthias Zenger
- * @version 1.0, 03/05/2004
- * @since 1
- */
-@deprecated("Proxying is deprecated due to lack of use and compiler-level support.", "2.11.0")
-abstract class PriorityQueueProxy[A](implicit ord: Ordering[A]) extends PriorityQueue[A]
- with Proxy
-{
- def self: PriorityQueue[A]
-
- /** Creates a new iterator over all elements contained in this
- * object.
- *
- * @return the new iterator
- */
- override def iterator: Iterator[A] = self.iterator
-
- /** Returns the length of this priority queue.
- */
- override def length: Int = self.length
-
- /** Checks if the queue is empty.
- *
- * @return true, iff there is no element in the queue.
- */
- override def isEmpty: Boolean = self.isEmpty
-
- /** Inserts a single element into the priority queue.
- *
- * @param elem the element to insert
- */
- override def +=(elem: A): this.type = { self += elem; this }
-
- /** Adds all elements provided by an iterator into the priority queue.
- *
- * @param it an iterator
- */
- override def ++=(it: TraversableOnce[A]): this.type = {
- self ++= it
- this
- }
-
- /** Adds all elements to the queue.
- *
- * @param elems the elements to add.
- */
- override def enqueue(elems: A*): Unit = self ++= elems
-
- /** Returns the element with the highest priority in the queue,
- * and removes this element from the queue.
- *
- * @return the element with the highest priority.
- */
- override def dequeue(): A = self.dequeue()
-
- /** Returns the element with the highest priority in the queue,
- * or throws an error if there is no element contained in the queue.
- *
- * @return the element with the highest priority.
- */
- override def head: A = self.head
-
- /** Removes all elements from the queue. After this operation is completed,
- * the queue will be empty.
- */
- override def clear(): Unit = self.clear()
-
- /** Returns a regular queue containing the same elements.
- */
- override def toQueue: Queue[A] = self.toQueue
-
- /** This method clones the priority queue.
- *
- * @return a priority queue with the same elements.
- */
- override def clone(): PriorityQueue[A] = new PriorityQueueProxy[A] {
- def self = PriorityQueueProxy.this.self.clone()
- }
-}
diff --git a/src/library/scala/collection/mutable/Queue.scala b/src/library/scala/collection/mutable/Queue.scala
index ad60173b64..fd5fe9aecc 100644
--- a/src/library/scala/collection/mutable/Queue.scala
+++ b/src/library/scala/collection/mutable/Queue.scala
@@ -143,7 +143,7 @@ extends MutableList[A]
/** Return the proper suffix of this list which starts with the first element that satisfies `p`.
* That element is unlinked from the list. If no element satisfies `p`, return None.
*/
- @deprecated("extractFirst inappropriately exposes implementation details. Use dequeue or dequeueAll.", "2.11.0")
+ @deprecated("extractFirst inappropriately exposes implementation details. Use dequeue or dequeueAll.", "2.11.0")
def extractFirst(start: LinkedList[A], p: A => Boolean): Option[LinkedList[A]] = {
if (isEmpty) None
else {
diff --git a/src/library/scala/collection/mutable/QueueProxy.scala b/src/library/scala/collection/mutable/QueueProxy.scala
index 22ff3306d5..e780cc2cf0 100644
--- a/src/library/scala/collection/mutable/QueueProxy.scala
+++ b/src/library/scala/collection/mutable/QueueProxy.scala
@@ -21,7 +21,7 @@ package mutable
* @version 1.1, 03/05/2004
* @since 1
*/
-@deprecated("Proxying is deprecated due to lack of use and compiler-level support.", "2.11.0")
+@deprecated("proxying is deprecated due to lack of use and compiler-level support", "2.11.0")
trait QueueProxy[A] extends Queue[A] with Proxy {
def self: Queue[A]
diff --git a/src/library/scala/collection/mutable/RedBlackTree.scala b/src/library/scala/collection/mutable/RedBlackTree.scala
new file mode 100644
index 0000000000..e4793242bf
--- /dev/null
+++ b/src/library/scala/collection/mutable/RedBlackTree.scala
@@ -0,0 +1,580 @@
+package scala.collection.mutable
+
+import scala.annotation.tailrec
+import scala.collection.Iterator
+
+/**
+ * An object containing the red-black tree implementation used by mutable `TreeMaps`.
+ *
+ * The trees implemented in this object are *not* thread safe.
+ *
+ * @author Rui Gonçalves
+ * @version 2.12
+ * @since 2.12
+ */
+private[collection] object RedBlackTree {
+
+ // ---- class structure ----
+
+ // For performance reasons, this implementation uses `null` references to represent leaves instead of a sentinel node.
+ // Currently, the internal nodes do not store their subtree size - only the tree object keeps track of their size.
+ // Therefore, while obtaining the size of the whole tree is O(1), knowing the number of entries inside a range is O(n)
+ // on the size of the range.
+
+ @SerialVersionUID(21575944040195605L)
+ final class Tree[A, B](var root: Node[A, B], var size: Int) extends Serializable
+
+ @SerialVersionUID(1950599696441054720L)
+ final class Node[A, B](var key: A, var value: B, var red: Boolean,
+ var left: Node[A, B], var right: Node[A, B], var parent: Node[A, B]) extends Serializable {
+
+ override def toString: String = "Node(" + key + ", " + value + ", " + red + ", " + left + ", " + right + ")"
+ }
+
+ object Tree {
+ def empty[A, B]: Tree[A, B] = new Tree(null, 0)
+ }
+
+ object Node {
+
+ @inline def apply[A, B](key: A, value: B, red: Boolean,
+ left: Node[A, B], right: Node[A, B], parent: Node[A, B]): Node[A, B] =
+ new Node(key, value, red, left, right, parent)
+
+ @inline def leaf[A, B](key: A, value: B, red: Boolean, parent: Node[A, B]): Node[A, B] =
+ new Node(key, value, red, null, null, parent)
+
+ def unapply[A, B](t: Node[A, B]) = Some((t.key, t.value, t.left, t.right, t.parent))
+ }
+
+ // ---- getters ----
+
+ def isRed(node: Node[_, _]) = (node ne null) && node.red
+ def isBlack(node: Node[_, _]) = (node eq null) || !node.red
+
+ // ---- size ----
+
+ def size(node: Node[_, _]): Int = if (node eq null) 0 else 1 + size(node.left) + size(node.right)
+ def size(tree: Tree[_, _]): Int = tree.size
+ def isEmpty(tree: Tree[_, _]) = tree.root eq null
+ def clear(tree: Tree[_, _]): Unit = { tree.root = null; tree.size = 0 }
+
+ // ---- search ----
+
+ def get[A: Ordering, B](tree: Tree[A, B], key: A): Option[B] = getNode(tree.root, key) match {
+ case null => None
+ case node => Some(node.value)
+ }
+
+ @tailrec private[this] def getNode[A, B](node: Node[A, B], key: A)(implicit ord: Ordering[A]): Node[A, B] =
+ if (node eq null) null
+ else {
+ val cmp = ord.compare(key, node.key)
+ if (cmp < 0) getNode(node.left, key)
+ else if (cmp > 0) getNode(node.right, key)
+ else node
+ }
+
+ def contains[A: Ordering](tree: Tree[A, _], key: A) = getNode(tree.root, key) ne null
+
+ def min[A, B](tree: Tree[A, B]): Option[(A, B)] = minNode(tree.root) match {
+ case null => None
+ case node => Some((node.key, node.value))
+ }
+
+ def minKey[A](tree: Tree[A, _]): Option[A] = minNode(tree.root) match {
+ case null => None
+ case node => Some(node.key)
+ }
+
+ private def minNode[A, B](node: Node[A, B]): Node[A, B] =
+ if (node eq null) null else minNodeNonNull(node)
+
+ @tailrec def minNodeNonNull[A, B](node: Node[A, B]): Node[A, B] =
+ if (node.left eq null) node else minNodeNonNull(node.left)
+
+ def max[A, B](tree: Tree[A, B]): Option[(A, B)] = maxNode(tree.root) match {
+ case null => None
+ case node => Some((node.key, node.value))
+ }
+
+ def maxKey[A](tree: Tree[A, _]): Option[A] = maxNode(tree.root) match {
+ case null => None
+ case node => Some(node.key)
+ }
+
+ private def maxNode[A, B](node: Node[A, B]): Node[A, B] =
+ if (node eq null) null else maxNodeNonNull(node)
+
+ @tailrec def maxNodeNonNull[A, B](node: Node[A, B]): Node[A, B] =
+ if (node.right eq null) node else maxNodeNonNull(node.right)
+
+ /**
+ * Returns the first (lowest) map entry with a key equal or greater than `key`. Returns `None` if there is no such
+ * node.
+ */
+ def minAfter[A, B](tree: Tree[A, B], key: A)(implicit ord: Ordering[A]): Option[(A, B)] =
+ minNodeAfter(tree.root, key) match {
+ case null => None
+ case node => Some((node.key, node.value))
+ }
+
+ def minKeyAfter[A](tree: Tree[A, _], key: A)(implicit ord: Ordering[A]): Option[A] =
+ minNodeAfter(tree.root, key) match {
+ case null => None
+ case node => Some(node.key)
+ }
+
+ private[this] def minNodeAfter[A, B](node: Node[A, B], key: A)(implicit ord: Ordering[A]): Node[A, B] = {
+ if (node eq null) null
+ else {
+ var y: Node[A, B] = null
+ var x = node
+ var cmp = 1
+ while ((x ne null) && cmp != 0) {
+ y = x
+ cmp = ord.compare(key, x.key)
+ x = if (cmp < 0) x.left else x.right
+ }
+ if (cmp <= 0) y else successor(y)
+ }
+ }
+
+ /**
+ * Returns the last (highest) map entry with a key smaller than `key`. Returns `None` if there is no such node.
+ */
+ def maxBefore[A, B](tree: Tree[A, B], key: A)(implicit ord: Ordering[A]): Option[(A, B)] =
+ maxNodeBefore(tree.root, key) match {
+ case null => None
+ case node => Some((node.key, node.value))
+ }
+
+ def maxKeyBefore[A](tree: Tree[A, _], key: A)(implicit ord: Ordering[A]): Option[A] =
+ maxNodeBefore(tree.root, key) match {
+ case null => None
+ case node => Some(node.key)
+ }
+
+ private[this] def maxNodeBefore[A, B](node: Node[A, B], key: A)(implicit ord: Ordering[A]): Node[A, B] = {
+ if (node eq null) null
+ else {
+ var y: Node[A, B] = null
+ var x = node
+ var cmp = 1
+ while ((x ne null) && cmp != 0) {
+ y = x
+ cmp = ord.compare(key, x.key)
+ x = if (cmp < 0) x.left else x.right
+ }
+ if (cmp > 0) y else predecessor(y)
+ }
+ }
+
+ // ---- insertion ----
+
+ def insert[A, B](tree: Tree[A, B], key: A, value: B)(implicit ord: Ordering[A]): Unit = {
+ var y: Node[A, B] = null
+ var x = tree.root
+ var cmp = 1
+ while ((x ne null) && cmp != 0) {
+ y = x
+ cmp = ord.compare(key, x.key)
+ x = if (cmp < 0) x.left else x.right
+ }
+
+ if (cmp == 0) y.value = value
+ else {
+ val z = Node.leaf(key, value, red = true, y)
+
+ if (y eq null) tree.root = z
+ else if (cmp < 0) y.left = z
+ else y.right = z
+
+ fixAfterInsert(tree, z)
+ tree.size += 1
+ }
+ }
+
+ private[this] def fixAfterInsert[A, B](tree: Tree[A, B], node: Node[A, B]): Unit = {
+ var z = node
+ while (isRed(z.parent)) {
+ if (z.parent eq z.parent.parent.left) {
+ val y = z.parent.parent.right
+ if (isRed(y)) {
+ z.parent.red = false
+ y.red = false
+ z.parent.parent.red = true
+ z = z.parent.parent
+ } else {
+ if (z eq z.parent.right) {
+ z = z.parent
+ rotateLeft(tree, z)
+ }
+ z.parent.red = false
+ z.parent.parent.red = true
+ rotateRight(tree, z.parent.parent)
+ }
+ } else { // symmetric cases
+ val y = z.parent.parent.left
+ if (isRed(y)) {
+ z.parent.red = false
+ y.red = false
+ z.parent.parent.red = true
+ z = z.parent.parent
+ } else {
+ if (z eq z.parent.left) {
+ z = z.parent
+ rotateRight(tree, z)
+ }
+ z.parent.red = false
+ z.parent.parent.red = true
+ rotateLeft(tree, z.parent.parent)
+ }
+ }
+ }
+ tree.root.red = false
+ }
+
+ // ---- deletion ----
+
+ def delete[A, B](tree: Tree[A, B], key: A)(implicit ord: Ordering[A]): Unit = {
+ val z = getNode(tree.root, key)
+ if (z ne null) {
+ var y = z
+ var yIsRed = y.red
+ var x: Node[A, B] = null
+ var xParent: Node[A, B] = null
+
+ if (z.left eq null) {
+ x = z.right
+ transplant(tree, z, z.right)
+ xParent = z.parent
+ }
+ else if (z.right eq null) {
+ x = z.left
+ transplant(tree, z, z.left)
+ xParent = z.parent
+ }
+ else {
+ y = minNodeNonNull(z.right)
+ yIsRed = y.red
+ x = y.right
+
+ if (y.parent eq z) xParent = y
+ else {
+ xParent = y.parent
+ transplant(tree, y, y.right)
+ y.right = z.right
+ y.right.parent = y
+ }
+ transplant(tree, z, y)
+ y.left = z.left
+ y.left.parent = y
+ y.red = z.red
+ }
+
+ if (!yIsRed) fixAfterDelete(tree, x, xParent)
+ tree.size -= 1
+ }
+ }
+
+ private[this] def fixAfterDelete[A, B](tree: Tree[A, B], node: Node[A, B], parent: Node[A, B]): Unit = {
+ var x = node
+ var xParent = parent
+ while ((x ne tree.root) && isBlack(x)) {
+ if (x eq xParent.left) {
+ var w = xParent.right
+ // assert(w ne null)
+
+ if (w.red) {
+ w.red = false
+ xParent.red = true
+ rotateLeft(tree, xParent)
+ w = xParent.right
+ }
+ if (isBlack(w.left) && isBlack(w.right)) {
+ w.red = true
+ x = xParent
+ } else {
+ if (isBlack(w.right)) {
+ w.left.red = false
+ w.red = true
+ rotateRight(tree, w)
+ w = xParent.right
+ }
+ w.red = xParent.red
+ xParent.red = false
+ w.right.red = false
+ rotateLeft(tree, xParent)
+ x = tree.root
+ }
+ } else { // symmetric cases
+ var w = xParent.left
+ // assert(w ne null)
+
+ if (w.red) {
+ w.red = false
+ xParent.red = true
+ rotateRight(tree, xParent)
+ w = xParent.left
+ }
+ if (isBlack(w.right) && isBlack(w.left)) {
+ w.red = true
+ x = xParent
+ } else {
+ if (isBlack(w.left)) {
+ w.right.red = false
+ w.red = true
+ rotateLeft(tree, w)
+ w = xParent.left
+ }
+ w.red = xParent.red
+ xParent.red = false
+ w.left.red = false
+ rotateRight(tree, xParent)
+ x = tree.root
+ }
+ }
+ xParent = x.parent
+ }
+ if (x ne null) x.red = false
+ }
+
+ // ---- helpers ----
+
+ /**
+ * Returns the node that follows `node` in an in-order tree traversal. If `node` has the maximum key (and is,
+ * therefore, the last node), this method returns `null`.
+ */
+ private[this] def successor[A, B](node: Node[A, B]): Node[A, B] = {
+ if (node.right ne null) minNodeNonNull(node.right)
+ else {
+ var x = node
+ var y = x.parent
+ while ((y ne null) && (x eq y.right)) {
+ x = y
+ y = y.parent
+ }
+ y
+ }
+ }
+
+ /**
+ * Returns the node that precedes `node` in an in-order tree traversal. If `node` has the minimum key (and is,
+ * therefore, the first node), this method returns `null`.
+ */
+ private[this] def predecessor[A, B](node: Node[A, B]): Node[A, B] = {
+ if (node.left ne null) maxNodeNonNull(node.left)
+ else {
+ var x = node
+ var y = x.parent
+ while ((y ne null) && (x eq y.left)) {
+ x = y
+ y = y.parent
+ }
+ y
+ }
+ }
+
+ private[this] def rotateLeft[A, B](tree: Tree[A, B], x: Node[A, B]): Unit = if (x ne null) {
+ // assert(x.right ne null)
+ val y = x.right
+ x.right = y.left
+
+ if (y.left ne null) y.left.parent = x
+ y.parent = x.parent
+
+ if (x.parent eq null) tree.root = y
+ else if (x eq x.parent.left) x.parent.left = y
+ else x.parent.right = y
+
+ y.left = x
+ x.parent = y
+ }
+
+ private[this] def rotateRight[A, B](tree: Tree[A, B], x: Node[A, B]): Unit = if (x ne null) {
+ // assert(x.left ne null)
+ val y = x.left
+ x.left = y.right
+
+ if (y.right ne null) y.right.parent = x
+ y.parent = x.parent
+
+ if (x.parent eq null) tree.root = y
+ else if (x eq x.parent.right) x.parent.right = y
+ else x.parent.left = y
+
+ y.right = x
+ x.parent = y
+ }
+
+ /**
+ * Transplant the node `from` to the place of node `to`. This is done by setting `from` as a child of `to`'s previous
+ * parent and setting `from`'s parent to the `to`'s previous parent. The children of `from` are left unchanged.
+ */
+ private[this] def transplant[A, B](tree: Tree[A, B], to: Node[A, B], from: Node[A, B]): Unit = {
+ if (to.parent eq null) tree.root = from
+ else if (to eq to.parent.left) to.parent.left = from
+ else to.parent.right = from
+
+ if (from ne null) from.parent = to.parent
+ }
+
+ // ---- tree traversal ----
+
+ def foreach[A, B, U](tree: Tree[A, B], f: ((A, B)) => U): Unit = foreachNode(tree.root, f)
+
+ private[this] def foreachNode[A, B, U](node: Node[A, B], f: ((A, B)) => U): Unit =
+ if (node ne null) foreachNodeNonNull(node, f)
+
+ private[this] def foreachNodeNonNull[A, B, U](node: Node[A, B], f: ((A, B)) => U): Unit = {
+ if (node.left ne null) foreachNodeNonNull(node.left, f)
+ f((node.key, node.value))
+ if (node.right ne null) foreachNodeNonNull(node.right, f)
+ }
+
+ def foreachKey[A, U](tree: Tree[A, _], f: A => U): Unit = foreachNodeKey(tree.root, f)
+
+ private[this] def foreachNodeKey[A, U](node: Node[A, _], f: A => U): Unit =
+ if (node ne null) foreachNodeKeyNonNull(node, f)
+
+ private[this] def foreachNodeKeyNonNull[A, U](node: Node[A, _], f: A => U): Unit = {
+ if (node.left ne null) foreachNodeKeyNonNull(node.left, f)
+ f(node.key)
+ if (node.right ne null) foreachNodeKeyNonNull(node.right, f)
+ }
+
+ def transform[A, B](tree: Tree[A, B], f: (A, B) => B): Unit = transformNode(tree.root, f)
+
+ private[this] def transformNode[A, B, U](node: Node[A, B], f: (A, B) => B): Unit =
+ if (node ne null) transformNodeNonNull(node, f)
+
+ private[this] def transformNodeNonNull[A, B, U](node: Node[A, B], f: (A, B) => B): Unit = {
+ if (node.left ne null) transformNodeNonNull(node.left, f)
+ node.value = f(node.key, node.value)
+ if (node.right ne null) transformNodeNonNull(node.right, f)
+ }
+
+ def iterator[A: Ordering, B](tree: Tree[A, B], start: Option[A] = None, end: Option[A] = None): Iterator[(A, B)] =
+ new EntriesIterator(tree, start, end)
+
+ def keysIterator[A: Ordering](tree: Tree[A, _], start: Option[A] = None, end: Option[A] = None): Iterator[A] =
+ new KeysIterator(tree, start, end)
+
+ def valuesIterator[A: Ordering, B](tree: Tree[A, B], start: Option[A] = None, end: Option[A] = None): Iterator[B] =
+ new ValuesIterator(tree, start, end)
+
+ private[this] abstract class TreeIterator[A, B, R](tree: Tree[A, B], start: Option[A], end: Option[A])
+ (implicit ord: Ordering[A]) extends Iterator[R] {
+
+ protected[this] def nextResult(node: Node[A, B]): R
+
+ def hasNext: Boolean = nextNode ne null
+
+ def next(): R = nextNode match {
+ case null => throw new NoSuchElementException("next on empty iterator")
+ case node =>
+ nextNode = successor(node)
+ setNullIfAfterEnd()
+ nextResult(node)
+ }
+
+ private[this] var nextNode: Node[A, B] = start match {
+ case None => minNode(tree.root)
+ case Some(from) => minNodeAfter(tree.root, from)
+ }
+
+ private[this] def setNullIfAfterEnd(): Unit =
+ if (end.isDefined && (nextNode ne null) && ord.compare(nextNode.key, end.get) >= 0)
+ nextNode = null
+
+ setNullIfAfterEnd()
+ }
+
+ private[this] final class EntriesIterator[A: Ordering, B](tree: Tree[A, B], start: Option[A], end: Option[A])
+ extends TreeIterator[A, B, (A, B)](tree, start, end) {
+
+ def nextResult(node: Node[A, B]) = (node.key, node.value)
+ }
+
+ private[this] final class KeysIterator[A: Ordering, B](tree: Tree[A, B], start: Option[A], end: Option[A])
+ extends TreeIterator[A, B, A](tree, start, end) {
+
+ def nextResult(node: Node[A, B]) = node.key
+ }
+
+ private[this] final class ValuesIterator[A: Ordering, B](tree: Tree[A, B], start: Option[A], end: Option[A])
+ extends TreeIterator[A, B, B](tree, start, end) {
+
+ def nextResult(node: Node[A, B]) = node.value
+ }
+
+ // ---- debugging ----
+
+ /**
+ * Checks if the tree is in a valid state. That happens if:
+ * - It is a valid binary search tree;
+ * - All red-black properties are satisfied;
+ * - All non-null nodes have their `parent` reference correct;
+ * - The size variable in `tree` corresponds to the actual size of the tree.
+ */
+ def isValid[A: Ordering, B](tree: Tree[A, B]): Boolean =
+ isValidBST(tree.root) && hasProperParentRefs(tree) && isValidRedBlackTree(tree) && size(tree.root) == tree.size
+
+ /**
+ * Returns true if all non-null nodes have their `parent` reference correct.
+ */
+ private[this] def hasProperParentRefs[A, B](tree: Tree[A, B]): Boolean = {
+
+ def hasProperParentRefs(node: Node[A, B]): Boolean = {
+ if (node eq null) true
+ else {
+ if ((node.left ne null) && (node.left.parent ne node) ||
+ (node.right ne null) && (node.right.parent ne node)) false
+ else hasProperParentRefs(node.left) && hasProperParentRefs(node.right)
+ }
+ }
+
+ if(tree.root eq null) true
+ else (tree.root.parent eq null) && hasProperParentRefs(tree.root)
+ }
+
+ /**
+ * Returns true if this node follows the properties of a binary search tree.
+ */
+ private[this] def isValidBST[A, B](node: Node[A, B])(implicit ord: Ordering[A]): Boolean = {
+ if (node eq null) true
+ else {
+ if ((node.left ne null) && (ord.compare(node.key, node.left.key) <= 0) ||
+ (node.right ne null) && (ord.compare(node.key, node.right.key) >= 0)) false
+ else isValidBST(node.left) && isValidBST(node.right)
+ }
+ }
+
+ /**
+ * Returns true if the tree has all the red-black tree properties: if the root node is black, if all children of red
+ * nodes are black and if the path from any node to any of its null children has the same number of black nodes.
+ */
+ private[this] def isValidRedBlackTree[A, B](tree: Tree[A, B]): Boolean = {
+
+ def noRedAfterRed(node: Node[A, B]): Boolean = {
+ if (node eq null) true
+ else if (node.red && (isRed(node.left) || isRed(node.right))) false
+ else noRedAfterRed(node.left) && noRedAfterRed(node.right)
+ }
+
+ def blackHeight(node: Node[A, B]): Int = {
+ if (node eq null) 1
+ else {
+ val lh = blackHeight(node.left)
+ val rh = blackHeight(node.right)
+
+ if (lh == -1 || lh != rh) -1
+ else if (isRed(node)) lh
+ else lh + 1
+ }
+ }
+
+ isBlack(tree.root) && noRedAfterRed(tree.root) && blackHeight(tree.root) >= 0
+ }
+}
diff --git a/src/library/scala/collection/mutable/ResizableArray.scala b/src/library/scala/collection/mutable/ResizableArray.scala
index c3047522e2..50d3513784 100644
--- a/src/library/scala/collection/mutable/ResizableArray.scala
+++ b/src/library/scala/collection/mutable/ResizableArray.scala
@@ -74,7 +74,7 @@ trait ResizableArray[A] extends IndexedSeq[A]
*/
override def copyToArray[B >: A](xs: Array[B], start: Int, len: Int) {
val len1 = len min (xs.length - start) min length
- Array.copy(array, 0, xs, start, len1)
+ if (len1 > 0) Array.copy(array, 0, xs, start, len1)
}
//##########################################################################
@@ -101,7 +101,7 @@ trait ResizableArray[A] extends IndexedSeq[A]
if (newSize > Int.MaxValue) newSize = Int.MaxValue
val newArray: Array[AnyRef] = new Array(newSize.toInt)
- scala.compat.Platform.arraycopy(array, 0, newArray, 0, size0)
+ java.lang.System.arraycopy(array, 0, newArray, 0, size0)
array = newArray
}
}
diff --git a/src/library/scala/collection/mutable/ReusableBuilder.scala b/src/library/scala/collection/mutable/ReusableBuilder.scala
new file mode 100644
index 0000000000..dee2cd6393
--- /dev/null
+++ b/src/library/scala/collection/mutable/ReusableBuilder.scala
@@ -0,0 +1,49 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2003-2016, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+\* */
+
+
+package scala
+package collection
+package mutable
+
+/** `ReusableBuilder` is a marker trait that indicates that a `Builder`
+ * can be reused to build more than one instance of a collection. In
+ * particular, calling `result` followed by `clear` will produce a
+ * collection and reset the builder to begin building a new collection
+ * of the same type.
+ *
+ * It is up to subclasses to implement this behavior, and to document any
+ * other behavior that varies from standard `ReusableBuilder` usage
+ * (e.g. operations being well-defined after a call to `result`, or allowing
+ * multiple calls to result to obtain different snapshots of a collection under
+ * construction).
+ *
+ * @tparam Elem the type of elements that get added to the builder.
+ * @tparam To the type of collection that it produced.
+ *
+ * @since 2.12
+ */
+trait ReusableBuilder[-Elem, +To] extends Builder[Elem, To] {
+ /** Clears the contents of this builder.
+ * After execution of this method, the builder will contain no elements.
+ *
+ * If executed immediately after a call to `result`, this allows a new
+ * instance of the same type of collection to be built.
+ */
+ override def clear(): Unit // Note: overriding for Scaladoc only!
+
+ /** Produces a collection from the added elements.
+ *
+ * After a call to `result`, the behavior of all other methods is undefined
+ * save for `clear`. If `clear` is called, then the builder is reset and
+ * may be used to build another instance.
+ *
+ * @return a collection containing the elements added to this builder.
+ */
+ override def result(): To // Note: overriding for Scaladoc only!
+}
diff --git a/src/library/scala/collection/mutable/SetBuilder.scala b/src/library/scala/collection/mutable/SetBuilder.scala
index 01bfdc96ed..5d1e9ffc3a 100644
--- a/src/library/scala/collection/mutable/SetBuilder.scala
+++ b/src/library/scala/collection/mutable/SetBuilder.scala
@@ -17,7 +17,9 @@ package mutable
* @param empty The empty element of the collection.
* @since 2.8
*/
-class SetBuilder[A, Coll <: scala.collection.Set[A] with scala.collection.SetLike[A, Coll]](empty: Coll) extends Builder[A, Coll] {
+class SetBuilder[A, Coll <: scala.collection.Set[A]
+with scala.collection.SetLike[A, Coll]](empty: Coll)
+extends ReusableBuilder[A, Coll] {
protected var elems: Coll = empty
def +=(x: A): this.type = { elems = elems + x; this }
def clear() { elems = empty }
diff --git a/src/library/scala/collection/mutable/SetLike.scala b/src/library/scala/collection/mutable/SetLike.scala
index 01075a2633..0797a83154 100644
--- a/src/library/scala/collection/mutable/SetLike.scala
+++ b/src/library/scala/collection/mutable/SetLike.scala
@@ -72,6 +72,17 @@ trait SetLike[A, +This <: SetLike[A, This] with Set[A]]
protected[this] override def parCombiner = ParSet.newCombiner[A]
+ /** Converts this $coll to a sequence.
+ *
+ * ```Note```: assumes a fast `size` method. Subclasses should override if this is not true.
+ */
+ override def toSeq: collection.Seq[A] = {
+ // ArrayBuffer for efficiency, preallocated to the right size.
+ val result = new ArrayBuffer[A](size)
+ foreach(result += _)
+ result
+ }
+
/** Adds an element to this $coll.
*
* @param elem the element to be added
@@ -213,7 +224,7 @@ trait SetLike[A, +This <: SetLike[A, This] with Set[A]]
* @throws UnsupportedOperationException
* if the message was not understood.
*/
- @deprecated("Scripting is deprecated.", "2.11.0")
+ @deprecated("scripting is deprecated", "2.11.0")
def <<(cmd: Message[A]): Unit = cmd match {
case Include(_, x) => this += x
case Remove(_, x) => this -= x
diff --git a/src/library/scala/collection/mutable/SetProxy.scala b/src/library/scala/collection/mutable/SetProxy.scala
index 74279507ff..43b6aa57af 100644
--- a/src/library/scala/collection/mutable/SetProxy.scala
+++ b/src/library/scala/collection/mutable/SetProxy.scala
@@ -18,7 +18,7 @@ package mutable
* @version 1.1, 09/05/2004
* @since 1
*/
-@deprecated("Proxying is deprecated due to lack of use and compiler-level support.", "2.11.0")
+@deprecated("proxying is deprecated due to lack of use and compiler-level support", "2.11.0")
trait SetProxy[A] extends Set[A] with SetProxyLike[A, Set[A]] {
override def repr = this
override def empty = new SetProxy[A] { val self = SetProxy.this.self.empty }
diff --git a/src/library/scala/collection/mutable/SortedMap.scala b/src/library/scala/collection/mutable/SortedMap.scala
new file mode 100644
index 0000000000..806b30e79a
--- /dev/null
+++ b/src/library/scala/collection/mutable/SortedMap.scala
@@ -0,0 +1,57 @@
+package scala
+package collection
+package mutable
+
+import generic._
+
+/**
+ * A mutable map whose keys are sorted.
+ *
+ * @tparam A the type of the keys contained in this sorted map.
+ * @tparam B the type of the values associated with the keys.
+ *
+ * @author Rui Gonçalves
+ * @version 2.12
+ * @since 2.12
+ *
+ * @define Coll mutable.SortedMap
+ * @define coll mutable sorted map
+ */
+trait SortedMap[A, B]
+ extends Map[A, B]
+ with collection.SortedMap[A, B]
+ with MapLike[A, B, SortedMap[A, B]]
+ with SortedMapLike[A, B, SortedMap[A, B]] {
+
+ override protected[this] def newBuilder: Builder[(A, B), SortedMap[A, B]] = SortedMap.newBuilder[A, B]
+
+ override def empty: SortedMap[A, B] = SortedMap.empty
+
+ override def updated[B1 >: B](key: A, value: B1): SortedMap[A, B1] = this + ((key, value))
+
+ override def +[B1 >: B](kv: (A, B1)): SortedMap[A, B1] = clone().asInstanceOf[SortedMap[A, B1]] += kv
+
+ override def +[B1 >: B](elem1: (A, B1), elem2: (A, B1), elems: (A, B1)*): SortedMap[A, B1] =
+ clone().asInstanceOf[SortedMap[A, B1]] += elem1 += elem2 ++= elems
+
+ override def ++[B1 >: B](xs: GenTraversableOnce[(A, B1)]): SortedMap[A, B1] =
+ clone().asInstanceOf[SortedMap[A, B1]] ++= xs.seq
+}
+
+/**
+ * $factoryInfo
+ *
+ * @define Coll mutable.SortedMap
+ * @define coll mutable sorted map
+ */
+object SortedMap extends MutableSortedMapFactory[SortedMap] {
+
+ def empty[A, B](implicit ord: Ordering[A]): SortedMap[A, B] = TreeMap.empty[A, B]
+
+ /** $sortedMapCanBuildFromInfo */
+ implicit def canBuildFrom[A, B](implicit ord: Ordering[A]): CanBuildFrom[Coll, (A, B), SortedMap[A, B]] =
+ new SortedMapCanBuildFrom[A, B]
+}
+
+/** Explicit instantiation of the `SortedMap` trait to reduce class file size in subclasses. */
+abstract class AbstractSortedMap[A, B] extends scala.collection.mutable.AbstractMap[A, B] with SortedMap[A, B]
diff --git a/src/library/scala/collection/mutable/SortedSet.scala b/src/library/scala/collection/mutable/SortedSet.scala
index 0f2fa75abd..304469916d 100644
--- a/src/library/scala/collection/mutable/SortedSet.scala
+++ b/src/library/scala/collection/mutable/SortedSet.scala
@@ -43,8 +43,13 @@ trait SortedSet[A] extends scala.collection.SortedSet[A] with scala.collection.S
*
*/
object SortedSet extends MutableSortedSetFactory[SortedSet] {
- implicit def canBuildFrom[A](implicit ord: Ordering[A]): CanBuildFrom[Coll, A, SortedSet[A]] = new SortedSetCanBuildFrom[A]
+ def canBuildFrom[A](implicit ord: Ordering[A]): CanBuildFrom[Coll, A, SortedSet[A]] = new SortedSetCanBuildFrom[A]
def empty[A](implicit ord: Ordering[A]): SortedSet[A] = TreeSet.empty[A]
+ // Force a declaration here so that BitSet (which does not inherit from SortedSetFactory) can be more specific
+ override implicit def newCanBuildFrom[A](implicit ord : Ordering[A]): CanBuildFrom[Coll, A, SortedSet[A]] = super.newCanBuildFrom
}
+
+/** Explicit instantiation of the `SortedSet` trait to reduce class file size in subclasses. */
+abstract class AbstractSortedSet[A] extends scala.collection.mutable.AbstractSet[A] with SortedSet[A]
diff --git a/src/library/scala/collection/mutable/Stack.scala b/src/library/scala/collection/mutable/Stack.scala
index 1a92f23b7b..28d50af1f9 100644
--- a/src/library/scala/collection/mutable/Stack.scala
+++ b/src/library/scala/collection/mutable/Stack.scala
@@ -54,6 +54,7 @@ object Stack extends SeqFactory[Stack] {
* @define mayNotTerminateInf
* @define willNotTerminateInf
*/
+@deprecated("Stack is an inelegant and potentially poorly-performing wrapper around List. Use a List assigned to a var instead.", "2.12.0")
class Stack[A] private (var elems: List[A])
extends AbstractSeq[A]
with Seq[A]
diff --git a/src/library/scala/collection/mutable/StackProxy.scala b/src/library/scala/collection/mutable/StackProxy.scala
index 81e63b05d2..ac52bbba21 100644
--- a/src/library/scala/collection/mutable/StackProxy.scala
+++ b/src/library/scala/collection/mutable/StackProxy.scala
@@ -19,7 +19,7 @@ package mutable
* @version 1.0, 10/05/2004
* @since 1
*/
-@deprecated("Proxying is deprecated due to lack of use and compiler-level support.", "2.11.0")
+@deprecated("proxying is deprecated due to lack of use and compiler-level support", "2.11.0")
trait StackProxy[A] extends Stack[A] with Proxy {
def self: Stack[A]
diff --git a/src/library/scala/collection/mutable/StringBuilder.scala b/src/library/scala/collection/mutable/StringBuilder.scala
index c56d40786e..b5b9498374 100644
--- a/src/library/scala/collection/mutable/StringBuilder.scala
+++ b/src/library/scala/collection/mutable/StringBuilder.scala
@@ -33,7 +33,7 @@ final class StringBuilder(private val underlying: JavaStringBuilder)
with java.lang.CharSequence
with IndexedSeq[Char]
with StringLike[StringBuilder]
- with Builder[Char, String]
+ with ReusableBuilder[Char, String]
with Serializable {
override protected[this] def thisCollection: StringBuilder = this
@@ -435,7 +435,11 @@ final class StringBuilder(private val underlying: JavaStringBuilder)
*/
override def mkString = toString
- /** Returns the result of this Builder (a String)
+ /** Returns the result of this Builder (a String).
+ *
+ * If this method is called multiple times, each call will result in a snapshot of the buffer at that point in time.
+ * In particular, a `StringBuilder` can be used to build multiple independent strings by emptying the buffer with `clear`
+ * after each call to `result`.
*
* @return the string assembled by this StringBuilder
*/
diff --git a/src/library/scala/collection/mutable/SynchronizedBuffer.scala b/src/library/scala/collection/mutable/SynchronizedBuffer.scala
index 8c646b0ce5..9c27f8b003 100644
--- a/src/library/scala/collection/mutable/SynchronizedBuffer.scala
+++ b/src/library/scala/collection/mutable/SynchronizedBuffer.scala
@@ -25,7 +25,7 @@ import script._
* @define Coll `SynchronizedBuffer`
* @define coll synchronized buffer
*/
-@deprecated("Synchronization via traits is deprecated as it is inherently unreliable. Consider java.util.concurrent.ConcurrentLinkedQueue as an alternative.", "2.11.0")
+@deprecated("Synchronization via traits is deprecated as it is inherently unreliable. Consider java.util.concurrent.ConcurrentLinkedQueue as an alternative.", "2.11.0")
trait SynchronizedBuffer[A] extends Buffer[A] {
import scala.collection.Traversable
@@ -162,7 +162,7 @@ trait SynchronizedBuffer[A] extends Buffer[A] {
super.clear()
}
- @deprecated("Scripting is deprecated.", "2.11.0")
+ @deprecated("scripting is deprecated", "2.11.0")
override def <<(cmd: Message[A]): Unit = synchronized {
super.<<(cmd)
}
diff --git a/src/library/scala/collection/mutable/SynchronizedMap.scala b/src/library/scala/collection/mutable/SynchronizedMap.scala
index 9876296ebe..8618798dbd 100644
--- a/src/library/scala/collection/mutable/SynchronizedMap.scala
+++ b/src/library/scala/collection/mutable/SynchronizedMap.scala
@@ -24,7 +24,7 @@ import scala.annotation.migration
* @define Coll `SynchronizedMap`
* @define coll synchronized map
*/
-@deprecated("Synchronization via traits is deprecated as it is inherently unreliable. Consider java.util.concurrent.ConcurrentHashMap as an alternative.", "2.11.0")
+@deprecated("Synchronization via traits is deprecated as it is inherently unreliable. Consider java.util.concurrent.ConcurrentHashMap as an alternative.", "2.11.0")
trait SynchronizedMap[A, B] extends Map[A, B] {
abstract override def get(key: A): Option[B] = synchronized { super.get(key) }
@@ -54,7 +54,7 @@ trait SynchronizedMap[A, B] extends Map[A, B] {
override def contains(key: A): Boolean = synchronized {super.contains(key) }
override def isDefinedAt(key: A) = synchronized { super.isDefinedAt(key) }
- // @deprecated("See Map.+ for explanation") override def +(kv: (A, B)): this.type = synchronized[this.type] { super.+(kv) }
+ // @deprecated("see Map.+ for explanation") override def +(kv: (A, B)): this.type = synchronized[this.type] { super.+(kv) }
// can't override -, -- same type!
// @deprecated override def -(key: A): Self = synchronized { super.-(key) }
diff --git a/src/library/scala/collection/mutable/SynchronizedPriorityQueue.scala b/src/library/scala/collection/mutable/SynchronizedPriorityQueue.scala
deleted file mode 100644
index d3c0b85f69..0000000000
--- a/src/library/scala/collection/mutable/SynchronizedPriorityQueue.scala
+++ /dev/null
@@ -1,101 +0,0 @@
-/* __ *\
-** ________ ___ / / ___ Scala API **
-** / __/ __// _ | / / / _ | (c) 2003-2013, LAMP/EPFL **
-** __\ \/ /__/ __ |/ /__/ __ | **
-** /____/\___/_/ |_/____/_/ | | **
-** |/ **
-\* */
-
-
-
-package scala
-package collection
-package mutable
-
-/** This class implements synchronized priority queues using a binary heap.
- * The elements of the queue have to be ordered in terms of the `Ordered[T]` class.
- *
- * @tparam A type of the elements contained in this synchronized priority queue
- * @param ord implicit ordering used to compared elements of type `A`
- *
- * @author Matthias Zenger
- * @version 1.0, 03/05/2004
- * @since 1
- * @define Coll `SynchronizedPriorityQueue`
- * @define coll synchronized priority queue
- */
-@deprecated("Comprehensive synchronization via selective overriding of methods is inherently unreliable. Consider java.util.concurrent.ConcurrentSkipListSet as an alternative.", "2.11.0")
-class SynchronizedPriorityQueue[A](implicit ord: Ordering[A]) extends PriorityQueue[A] {
-
- /** Checks if the queue is empty.
- *
- * @return true, iff there is no element in the queue.
- */
- override def isEmpty: Boolean = synchronized { super.isEmpty }
-
- /** Inserts a single element into the priority queue.
- *
- * @param elem the element to insert
- */
- override def +=(elem: A): this.type = {
- synchronized {
- super.+=(elem)
- }
- this
- }
-
- /** Adds all elements of a traversable object into the priority queue.
- *
- * @param xs a traversable object
- */
- override def ++=(xs: TraversableOnce[A]): this.type = {
- synchronized {
- super.++=(xs)
- }
- this
- }
-
- /** Adds all elements to the queue.
- *
- * @param elems the elements to add.
- */
- override def enqueue(elems: A*): Unit = synchronized { super.++=(elems) }
-
- /** Returns the element with the highest priority in the queue,
- * and removes this element from the queue.
- *
- * @return the element with the highest priority.
- */
- override def dequeue(): A = synchronized { super.dequeue() }
-
- /** Returns the element with the highest priority in the queue,
- * or throws an error if there is no element contained in the queue.
- *
- * @return the element with the highest priority.
- */
- override def head: A = synchronized { super.head }
-
- /** Removes all elements from the queue. After this operation is completed,
- * the queue will be empty.
- */
- override def clear(): Unit = synchronized { super.clear() }
-
- /** Returns an iterator which yield all the elements of the priority
- * queue in descending priority order.
- *
- * @return an iterator over all elements sorted in descending order.
- */
- override def iterator: Iterator[A] = synchronized { super.iterator }
-
- /** Checks if two queues are structurally identical.
- *
- * @return true, iff both queues contain the same sequence of elements.
- */
- override def equals(that: Any): Boolean = synchronized { super.equals(that) }
-
- /** Returns a textual representation of a queue as a string.
- *
- * @return the string representation of this queue.
- */
- override def toString(): String = synchronized { super.toString() }
-}
diff --git a/src/library/scala/collection/mutable/SynchronizedQueue.scala b/src/library/scala/collection/mutable/SynchronizedQueue.scala
index 48e40ab27f..ee44f07df2 100644
--- a/src/library/scala/collection/mutable/SynchronizedQueue.scala
+++ b/src/library/scala/collection/mutable/SynchronizedQueue.scala
@@ -25,7 +25,7 @@ package mutable
* @define Coll `SynchronizedQueue`
* @define coll synchronized queue
*/
-@deprecated("Synchronization via selective overriding of methods is inherently unreliable. Consider java.util.concurrent.ConcurrentLinkedQueue as an alternative.", "2.11.0")
+@deprecated("Synchronization via selective overriding of methods is inherently unreliable. Consider java.util.concurrent.ConcurrentLinkedQueue as an alternative.", "2.11.0")
class SynchronizedQueue[A] extends Queue[A] {
/** Checks if the queue is empty.
*
diff --git a/src/library/scala/collection/mutable/SynchronizedSet.scala b/src/library/scala/collection/mutable/SynchronizedSet.scala
index dd842f26ce..399630eb3c 100644
--- a/src/library/scala/collection/mutable/SynchronizedSet.scala
+++ b/src/library/scala/collection/mutable/SynchronizedSet.scala
@@ -24,7 +24,7 @@ import script._
* @define Coll `SynchronizedSet`
* @define coll synchronized set
*/
-@deprecated("Synchronization via traits is deprecated as it is inherently unreliable. Consider java.util.concurrent.ConcurrentHashMap[A,Unit] as an alternative.", "2.11.0")
+@deprecated("Synchronization via traits is deprecated as it is inherently unreliable. Consider java.util.concurrent.ConcurrentHashMap[A,Unit] as an alternative.", "2.11.0")
trait SynchronizedSet[A] extends Set[A] {
abstract override def size: Int = synchronized {
super.size
@@ -94,7 +94,7 @@ trait SynchronizedSet[A] extends Set[A] {
super.toString
}
- @deprecated("Scripting is deprecated.", "2.11.0")
+ @deprecated("scripting is deprecated", "2.11.0")
override def <<(cmd: Message[A]): Unit = synchronized {
super.<<(cmd)
}
diff --git a/src/library/scala/collection/mutable/SynchronizedStack.scala b/src/library/scala/collection/mutable/SynchronizedStack.scala
index bbb6f5a9bb..2954a1f768 100644
--- a/src/library/scala/collection/mutable/SynchronizedStack.scala
+++ b/src/library/scala/collection/mutable/SynchronizedStack.scala
@@ -25,9 +25,8 @@ package mutable
* @define Coll `SynchronizedStack`
* @define coll synchronized stack
*/
-@deprecated("Synchronization via selective overriding of methods is inherently unreliable. Consider java.util.concurrent.LinkedBlockingDequeue instead.", "2.11.0")
+@deprecated("Synchronization via selective overriding of methods is inherently unreliable. Consider java.util.concurrent.LinkedBlockingDequeue instead.", "2.11.0")
class SynchronizedStack[A] extends Stack[A] {
- import scala.collection.Traversable
/** Checks if the stack is empty.
*
diff --git a/src/library/scala/collection/mutable/TreeMap.scala b/src/library/scala/collection/mutable/TreeMap.scala
new file mode 100644
index 0000000000..14ae7c9c8c
--- /dev/null
+++ b/src/library/scala/collection/mutable/TreeMap.scala
@@ -0,0 +1,188 @@
+package scala
+package collection
+package mutable
+
+import scala.collection.generic._
+import scala.collection.mutable.{RedBlackTree => RB}
+
+/**
+ * $factoryInfo
+ *
+ * @define Coll mutable.TreeMap
+ * @define coll mutable tree map
+ */
+object TreeMap extends MutableSortedMapFactory[TreeMap] {
+
+ def empty[A, B](implicit ord: Ordering[A]) = new TreeMap[A, B]()(ord)
+
+ /** $sortedMapCanBuildFromInfo */
+ implicit def canBuildFrom[A, B](implicit ord: Ordering[A]): CanBuildFrom[Coll, (A, B), TreeMap[A, B]] =
+ new SortedMapCanBuildFrom[A, B]
+}
+
+/**
+ * A mutable sorted map implemented using a mutable red-black tree as underlying data structure.
+ *
+ * @param ordering the implicit ordering used to compare objects of type `A`.
+ * @tparam A the type of the keys contained in this tree map.
+ * @tparam B the type of the values associated with the keys.
+ *
+ * @author Rui Gonçalves
+ * @version 2.12
+ * @since 2.12
+ *
+ * @define Coll mutable.TreeMap
+ * @define coll mutable tree map
+ */
+@SerialVersionUID(-2558985573956740112L)
+sealed class TreeMap[A, B] private (tree: RB.Tree[A, B])(implicit val ordering: Ordering[A])
+ extends AbstractSortedMap[A, B]
+ with SortedMap[A, B]
+ with MapLike[A, B, TreeMap[A, B]]
+ with SortedMapLike[A, B, TreeMap[A, B]]
+ with Serializable {
+
+ /**
+ * Creates an empty `TreeMap`.
+ * @param ord the implicit ordering used to compare objects of type `A`.
+ * @return an empty `TreeMap`.
+ */
+ def this()(implicit ord: Ordering[A]) = this(RB.Tree.empty)(ord)
+
+ override def empty = TreeMap.empty
+ override protected[this] def newBuilder = TreeMap.newBuilder[A, B]
+
+ /**
+ * Creates a ranged projection of this map. Any mutations in the ranged projection will update the original map and
+ * vice versa.
+ *
+ * Only entries with keys between this projection's key range will ever appear as elements of this map, independently
+ * of whether the entries are added through the original map or through this view. That means that if one inserts a
+ * key-value in a view whose key is outside the view's bounds, calls to `get` or `contains` will _not_ consider the
+ * newly added entry. Mutations are always reflected in the original map, though.
+ *
+ * @param from the lower bound (inclusive) of this projection wrapped in a `Some`, or `None` if there is no lower
+ * bound.
+ * @param until the upper bound (exclusive) of this projection wrapped in a `Some`, or `None` if there is no upper
+ * bound.
+ */
+ def rangeImpl(from: Option[A], until: Option[A]): TreeMap[A, B] = new TreeMapView(from, until)
+
+ def -=(key: A): this.type = { RB.delete(tree, key); this }
+ def +=(kv: (A, B)): this.type = { RB.insert(tree, kv._1, kv._2); this }
+
+ def get(key: A) = RB.get(tree, key)
+
+ def iterator = RB.iterator(tree)
+ def iteratorFrom(start: A) = RB.iterator(tree, Some(start))
+ def keysIteratorFrom(start: A) = RB.keysIterator(tree, Some(start))
+ def valuesIteratorFrom(start: A) = RB.valuesIterator(tree, Some(start))
+
+ override def size = RB.size(tree)
+ override def isEmpty = RB.isEmpty(tree)
+ override def contains(key: A) = RB.contains(tree, key)
+
+ override def head = RB.min(tree).get
+ override def headOption = RB.min(tree)
+ override def last = RB.max(tree).get
+ override def lastOption = RB.max(tree)
+
+ override def keysIterator = RB.keysIterator(tree)
+ override def valuesIterator = RB.valuesIterator(tree)
+
+ override def foreach[U](f: ((A, B)) => U): Unit = RB.foreach(tree, f)
+ override def transform(f: (A, B) => B) = { RB.transform(tree, f); this }
+ override def clear(): Unit = RB.clear(tree)
+
+ override def stringPrefix = "TreeMap"
+
+ /**
+ * A ranged projection of a [[TreeMap]]. Mutations on this map affect the original map and vice versa.
+ *
+ * Only entries with keys between this projection's key range will ever appear as elements of this map, independently
+ * of whether the entries are added through the original map or through this view. That means that if one inserts a
+ * key-value in a view whose key is outside the view's bounds, calls to `get` or `contains` will _not_ consider the
+ * newly added entry. Mutations are always reflected in the original map, though.
+ *
+ * @param from the lower bound (inclusive) of this projection wrapped in a `Some`, or `None` if there is no lower
+ * bound.
+ * @param until the upper bound (exclusive) of this projection wrapped in a `Some`, or `None` if there is no upper
+ * bound.
+ */
+ @SerialVersionUID(2219159283273389116L)
+ private[this] final class TreeMapView(from: Option[A], until: Option[A]) extends TreeMap[A, B](tree) {
+
+ /**
+ * Given a possible new lower bound, chooses and returns the most constraining one (the maximum).
+ */
+ private[this] def pickLowerBound(newFrom: Option[A]): Option[A] = (from, newFrom) match {
+ case (Some(fr), Some(newFr)) => Some(ordering.max(fr, newFr))
+ case (None, _) => newFrom
+ case _ => from
+ }
+
+ /**
+ * Given a possible new upper bound, chooses and returns the most constraining one (the minimum).
+ */
+ private[this] def pickUpperBound(newUntil: Option[A]): Option[A] = (until, newUntil) match {
+ case (Some(unt), Some(newUnt)) => Some(ordering.min(unt, newUnt))
+ case (None, _) => newUntil
+ case _ => until
+ }
+
+ /**
+ * Returns true if the argument is inside the view bounds (between `from` and `until`).
+ */
+ private[this] def isInsideViewBounds(key: A): Boolean = {
+ val afterFrom = from.isEmpty || ordering.compare(from.get, key) <= 0
+ val beforeUntil = until.isEmpty || ordering.compare(key, until.get) < 0
+ afterFrom && beforeUntil
+ }
+
+ override def rangeImpl(from: Option[A], until: Option[A]): TreeMap[A, B] =
+ new TreeMapView(pickLowerBound(from), pickUpperBound(until))
+
+ override def get(key: A) = if (isInsideViewBounds(key)) RB.get(tree, key) else None
+
+ override def iterator = RB.iterator(tree, from, until)
+ override def iteratorFrom(start: A) = RB.iterator(tree, pickLowerBound(Some(start)), until)
+ override def keysIteratorFrom(start: A) = RB.keysIterator(tree, pickLowerBound(Some(start)), until)
+ override def valuesIteratorFrom(start: A) = RB.valuesIterator(tree, pickLowerBound(Some(start)), until)
+
+ override def size = iterator.length
+ override def isEmpty = !iterator.hasNext
+ override def contains(key: A) = isInsideViewBounds(key) && RB.contains(tree, key)
+
+ override def head = headOption.get
+ override def headOption = {
+ val entry = if (from.isDefined) RB.minAfter(tree, from.get) else RB.min(tree)
+ (entry, until) match {
+ case (Some(e), Some(unt)) if ordering.compare(e._1, unt) >= 0 => None
+ case _ => entry
+ }
+ }
+
+ override def last = lastOption.get
+ override def lastOption = {
+ val entry = if (until.isDefined) RB.maxBefore(tree, until.get) else RB.max(tree)
+ (entry, from) match {
+ case (Some(e), Some(fr)) if ordering.compare(e._1, fr) < 0 => None
+ case _ => entry
+ }
+ }
+
+ // Using the iterator should be efficient enough; if performance is deemed a problem later, specialized
+ // `foreach(f, from, until)` and `transform(f, from, until)` methods can be created in `RedBlackTree`. See
+ // https://github.com/scala/scala/pull/4608#discussion_r34307985 for a discussion about this.
+ override def foreach[U](f: ((A, B)) => U): Unit = iterator.foreach(f)
+ override def transform(f: (A, B) => B) = {
+ iterator.foreach { case (key, value) => update(key, f(key, value)) }
+ this
+ }
+
+ override def valuesIterator: Iterator[B] = RB.valuesIterator(tree, from, until)
+ override def keysIterator: Iterator[A] = RB.keysIterator(tree, from, until)
+
+ override def clone() = super.clone().rangeImpl(from, until)
+ }
+}
diff --git a/src/library/scala/collection/mutable/TreeSet.scala b/src/library/scala/collection/mutable/TreeSet.scala
index f849eea569..ada6f145ad 100644
--- a/src/library/scala/collection/mutable/TreeSet.scala
+++ b/src/library/scala/collection/mutable/TreeSet.scala
@@ -11,8 +11,7 @@ package collection
package mutable
import generic._
-import scala.collection.immutable.{RedBlackTree => RB}
-import scala.runtime.ObjectRef
+import scala.collection.mutable.{RedBlackTree => RB}
/**
* @define Coll `mutable.TreeSet`
@@ -29,88 +28,162 @@ object TreeSet extends MutableSortedSetFactory[TreeSet] {
*/
def empty[A](implicit ordering: Ordering[A]) = new TreeSet[A]()
+ /** $sortedMapCanBuildFromInfo */
+ implicit def canBuildFrom[A](implicit ord: Ordering[A]): CanBuildFrom[Coll, A, TreeSet[A]] =
+ new SortedSetCanBuildFrom[A]
}
/**
- * A mutable SortedSet using an immutable RedBlack Tree as underlying data structure.
+ * A mutable sorted set implemented using a mutable red-black tree as underlying data structure.
*
- * @author Lucien Pereira
+ * @param ordering the implicit ordering used to compare objects of type `A`.
+ * @tparam A the type of the keys contained in this tree set.
+ *
+ * @author Rui Gonçalves
+ * @version 2.12
+ * @since 2.10
*
+ * @define Coll mutable.TreeSet
+ * @define coll mutable tree set
*/
-@deprecatedInheritance("TreeSet is not designed to enable meaningful subclassing.", "2.11.0")
-class TreeSet[A] private (treeRef: ObjectRef[RB.Tree[A, Null]], from: Option[A], until: Option[A])(implicit val ordering: Ordering[A])
- extends SortedSet[A] with SetLike[A, TreeSet[A]]
- with SortedSetLike[A, TreeSet[A]] with Set[A] with Serializable {
+// Original API designed in part by Lucien Pereira
+@SerialVersionUID(-3642111301929493640L)
+sealed class TreeSet[A] private (tree: RB.Tree[A, Null])(implicit val ordering: Ordering[A])
+ extends AbstractSortedSet[A]
+ with SortedSet[A]
+ with SetLike[A, TreeSet[A]]
+ with SortedSetLike[A, TreeSet[A]]
+ with Serializable {
if (ordering eq null)
throw new NullPointerException("ordering must not be null")
- def this()(implicit ordering: Ordering[A]) = this(new ObjectRef(null), None, None)
+ /**
+ * Creates an empty `TreeSet`.
+ * @param ord the implicit ordering used to compare objects of type `A`.
+ * @return an empty `TreeSet`.
+ */
+ def this()(implicit ord: Ordering[A]) = this(RB.Tree.empty)(ord)
- override def size: Int = RB.countInRange(treeRef.elem, from, until)
+ override def empty = TreeSet.empty
+ override protected[this] def newBuilder = TreeSet.newBuilder[A]
- override def stringPrefix = "TreeSet"
+ /**
+ * Creates a ranged projection of this set. Any mutations in the ranged projection affect will update the original set
+ * and vice versa.
+ *
+ * Only keys between this projection's key range will ever appear as elements of this set, independently of whether
+ * the elements are added through the original set or through this view. That means that if one inserts an element in
+ * a view whose key is outside the view's bounds, calls to `contains` will _not_ consider the newly added element.
+ * Mutations are always reflected in the original set, though.
+ *
+ * @param from the lower bound (inclusive) of this projection wrapped in a `Some`, or `None` if there is no lower
+ * bound.
+ * @param until the upper bound (exclusive) of this projection wrapped in a `Some`, or `None` if there is no upper
+ * bound.
+ */
+ def rangeImpl(from: Option[A], until: Option[A]): TreeSet[A] = new TreeSetView(from, until)
- override def empty: TreeSet[A] = TreeSet.empty
+ def -=(key: A): this.type = { RB.delete(tree, key); this }
+ def +=(elem: A): this.type = { RB.insert(tree, elem, null); this }
- private def pickBound(comparison: (A, A) => A, oldBound: Option[A], newBound: Option[A]) = (newBound, oldBound) match {
- case (Some(newB), Some(oldB)) => Some(comparison(newB, oldB))
- case (None, _) => oldBound
- case _ => newBound
- }
+ def contains(elem: A) = RB.contains(tree, elem)
- override def rangeImpl(fromArg: Option[A], untilArg: Option[A]): TreeSet[A] = {
- val newFrom = pickBound(ordering.max, fromArg, from)
- val newUntil = pickBound(ordering.min, untilArg, until)
+ def iterator = RB.keysIterator(tree)
+ def keysIteratorFrom(start: A) = RB.keysIterator(tree, Some(start))
+ override def iteratorFrom(start: A) = RB.keysIterator(tree, Some(start))
- new TreeSet(treeRef, newFrom, newUntil)
- }
+ override def size = RB.size(tree)
+ override def isEmpty = RB.isEmpty(tree)
- override def -=(elem: A): this.type = {
- treeRef.elem = RB.delete(treeRef.elem, elem)
- this
- }
+ override def head = RB.minKey(tree).get
+ override def headOption = RB.minKey(tree)
+ override def last = RB.maxKey(tree).get
+ override def lastOption = RB.maxKey(tree)
- override def +=(elem: A): this.type = {
- treeRef.elem = RB.update(treeRef.elem, elem, null, overwrite = false)
- this
- }
+ override def foreach[U](f: A => U): Unit = RB.foreachKey(tree, f)
+ override def clear(): Unit = RB.clear(tree)
+
+ override def stringPrefix = "TreeSet"
/**
- * Thanks to the immutable nature of the
- * underlying Tree, we can share it with
- * the clone. So clone complexity in time is O(1).
+ * A ranged projection of a [[TreeSet]]. Mutations on this set affect the original set and vice versa.
*
+ * Only keys between this projection's key range will ever appear as elements of this set, independently of whether
+ * the elements are added through the original set or through this view. That means that if one inserts an element in
+ * a view whose key is outside the view's bounds, calls to `contains` will _not_ consider the newly added element.
+ * Mutations are always reflected in the original set, though.
+ *
+ * @param from the lower bound (inclusive) of this projection wrapped in a `Some`, or `None` if there is no lower
+ * bound.
+ * @param until the upper bound (exclusive) of this projection wrapped in a `Some`, or `None` if there is no upper
+ * bound.
*/
- override def clone(): TreeSet[A] =
- new TreeSet[A](new ObjectRef(treeRef.elem), from, until)
-
- private val notProjection = !(from.isDefined || until.isDefined)
+ @SerialVersionUID(7087824939194006086L)
+ private[this] final class TreeSetView(from: Option[A], until: Option[A]) extends TreeSet[A](tree) {
+
+ /**
+ * Given a possible new lower bound, chooses and returns the most constraining one (the maximum).
+ */
+ private[this] def pickLowerBound(newFrom: Option[A]): Option[A] = (from, newFrom) match {
+ case (Some(fr), Some(newFr)) => Some(ordering.max(fr, newFr))
+ case (None, _) => newFrom
+ case _ => from
+ }
- override def contains(elem: A): Boolean = {
- def leftAcceptable: Boolean = from match {
- case Some(lb) => ordering.gteq(elem, lb)
- case _ => true
+ /**
+ * Given a possible new upper bound, chooses and returns the most constraining one (the minimum).
+ */
+ private[this] def pickUpperBound(newUntil: Option[A]): Option[A] = (until, newUntil) match {
+ case (Some(unt), Some(newUnt)) => Some(ordering.min(unt, newUnt))
+ case (None, _) => newUntil
+ case _ => until
}
- def rightAcceptable: Boolean = until match {
- case Some(ub) => ordering.lt(elem, ub)
- case _ => true
+ /**
+ * Returns true if the argument is inside the view bounds (between `from` and `until`).
+ */
+ private[this] def isInsideViewBounds(key: A): Boolean = {
+ val afterFrom = from.isEmpty || ordering.compare(from.get, key) <= 0
+ val beforeUntil = until.isEmpty || ordering.compare(key, until.get) < 0
+ afterFrom && beforeUntil
}
- (notProjection || (leftAcceptable && rightAcceptable)) &&
- RB.contains(treeRef.elem, elem)
- }
+ override def rangeImpl(from: Option[A], until: Option[A]): TreeSet[A] =
+ new TreeSetView(pickLowerBound(from), pickUpperBound(until))
+
+ override def contains(key: A) = isInsideViewBounds(key) && RB.contains(tree, key)
+
+ override def iterator = RB.keysIterator(tree, from, until)
+ override def keysIteratorFrom(start: A) = RB.keysIterator(tree, pickLowerBound(Some(start)), until)
+ override def iteratorFrom(start: A) = RB.keysIterator(tree, pickLowerBound(Some(start)), until)
- override def iterator: Iterator[A] = iteratorFrom(None)
+ override def size = iterator.length
+ override def isEmpty = !iterator.hasNext
- override def keysIteratorFrom(start: A) = iteratorFrom(Some(start))
+ override def head = headOption.get
+ override def headOption = {
+ val elem = if (from.isDefined) RB.minKeyAfter(tree, from.get) else RB.minKey(tree)
+ (elem, until) match {
+ case (Some(e), Some(unt)) if ordering.compare(e, unt) >= 0 => None
+ case _ => elem
+ }
+ }
- private def iteratorFrom(start: Option[A]) = {
- val it = RB.keysIterator(treeRef.elem, pickBound(ordering.max, from, start))
- until match {
- case None => it
- case Some(ub) => it takeWhile (k => ordering.lt(k, ub))
+ override def last = lastOption.get
+ override def lastOption = {
+ val elem = if (until.isDefined) RB.maxKeyBefore(tree, until.get) else RB.maxKey(tree)
+ (elem, from) match {
+ case (Some(e), Some(fr)) if ordering.compare(e, fr) < 0 => None
+ case _ => elem
+ }
}
+
+ // Using the iterator should be efficient enough; if performance is deemed a problem later, a specialized
+ // `foreachKey(f, from, until)` method can be created in `RedBlackTree`. See
+ // https://github.com/scala/scala/pull/4608#discussion_r34307985 for a discussion about this.
+ override def foreach[U](f: A => U): Unit = iterator.foreach(f)
+
+ override def clone() = super.clone().rangeImpl(from, until)
}
}
diff --git a/src/library/scala/collection/mutable/UnrolledBuffer.scala b/src/library/scala/collection/mutable/UnrolledBuffer.scala
index 2212486bcf..b49d009a17 100644
--- a/src/library/scala/collection/mutable/UnrolledBuffer.scala
+++ b/src/library/scala/collection/mutable/UnrolledBuffer.scala
@@ -43,8 +43,7 @@ import scala.reflect.ClassTag
*
*/
@SerialVersionUID(1L)
-@deprecatedInheritance("UnrolledBuffer is not designed to enable meaningful subclassing.", "2.11.0")
-class UnrolledBuffer[T](implicit val tag: ClassTag[T])
+sealed class UnrolledBuffer[T](implicit val tag: ClassTag[T])
extends scala.collection.mutable.AbstractBuffer[T]
with scala.collection.mutable.Buffer[T]
with scala.collection.mutable.BufferLike[T, UnrolledBuffer[T]]
@@ -350,3 +349,11 @@ object UnrolledBuffer extends ClassTagTraversableFactory[UnrolledBuffer] {
}
}
+
+
+// This is used by scala.collection.parallel.mutable.UnrolledParArrayCombiner:
+// Todo -- revisit whether inheritance is the best way to achieve this functionality
+private[collection] class DoublingUnrolledBuffer[T](implicit t: ClassTag[T]) extends UnrolledBuffer[T]()(t) {
+ override def calcNextLength(sz: Int) = if (sz < 10000) sz * 2 else sz
+ protected override def newUnrolled = new UnrolledBuffer.Unrolled[T](0, new Array[T](4), null, this)
+}
diff --git a/src/library/scala/collection/mutable/WrappedArray.scala b/src/library/scala/collection/mutable/WrappedArray.scala
index 8740bda835..0b5ebe7e9a 100644
--- a/src/library/scala/collection/mutable/WrappedArray.scala
+++ b/src/library/scala/collection/mutable/WrappedArray.scala
@@ -13,9 +13,12 @@ package collection
package mutable
import scala.reflect.ClassTag
-import scala.runtime.ScalaRunTime._
+import scala.runtime.BoxedUnit
import scala.collection.generic._
import scala.collection.parallel.mutable.ParArray
+import scala.util.hashing.MurmurHash3
+
+import java.util.Arrays
/**
* A class representing `Array[T]`.
@@ -46,7 +49,7 @@ extends AbstractSeq[T]
def elemTag: ClassTag[T]
@deprecated("use elemTag instead", "2.10.0")
- def elemManifest: ClassManifest[T] = ClassManifest.fromClass[T](arrayElementClass(elemTag).asInstanceOf[Class[T]])
+ def elemManifest: ClassManifest[T] = ClassManifest.fromClass[T](elemTag.runtimeClass.asInstanceOf[Class[T]])
/** The length of the array */
def length: Int
@@ -63,10 +66,10 @@ extends AbstractSeq[T]
override def par = ParArray.handoff(array)
private def elementClass: Class[_] =
- arrayElementClass(array.getClass)
+ array.getClass.getComponentType
override def toArray[U >: T : ClassTag]: Array[U] = {
- val thatElementClass = arrayElementClass(implicitly[ClassTag[U]])
+ val thatElementClass = implicitly[ClassTag[U]].runtimeClass
if (elementClass eq thatElementClass)
array.asInstanceOf[Array[U]]
else
@@ -122,10 +125,15 @@ object WrappedArray {
def newBuilder[A]: Builder[A, IndexedSeq[A]] = new ArrayBuffer
final class ofRef[T <: AnyRef](val array: Array[T]) extends WrappedArray[T] with Serializable {
- lazy val elemTag = ClassTag[T](arrayElementClass(array.getClass))
+ lazy val elemTag = ClassTag[T](array.getClass.getComponentType)
def length: Int = array.length
def apply(index: Int): T = array(index).asInstanceOf[T]
def update(index: Int, elem: T) { array(index) = elem }
+ override def hashCode = MurmurHash3.wrappedArrayHash(array)
+ override def equals(that: Any) = that match {
+ case that: ofRef[_] => Arrays.equals(array.asInstanceOf[Array[AnyRef]], that.array.asInstanceOf[Array[AnyRef]])
+ case _ => super.equals(that)
+ }
}
final class ofByte(val array: Array[Byte]) extends WrappedArray[Byte] with Serializable {
@@ -133,6 +141,11 @@ object WrappedArray {
def length: Int = array.length
def apply(index: Int): Byte = array(index)
def update(index: Int, elem: Byte) { array(index) = elem }
+ override def hashCode = MurmurHash3.wrappedBytesHash(array)
+ override def equals(that: Any) = that match {
+ case that: ofByte => Arrays.equals(array, that.array)
+ case _ => super.equals(that)
+ }
}
final class ofShort(val array: Array[Short]) extends WrappedArray[Short] with Serializable {
@@ -140,6 +153,11 @@ object WrappedArray {
def length: Int = array.length
def apply(index: Int): Short = array(index)
def update(index: Int, elem: Short) { array(index) = elem }
+ override def hashCode = MurmurHash3.wrappedArrayHash(array)
+ override def equals(that: Any) = that match {
+ case that: ofShort => Arrays.equals(array, that.array)
+ case _ => super.equals(that)
+ }
}
final class ofChar(val array: Array[Char]) extends WrappedArray[Char] with Serializable {
@@ -147,6 +165,11 @@ object WrappedArray {
def length: Int = array.length
def apply(index: Int): Char = array(index)
def update(index: Int, elem: Char) { array(index) = elem }
+ override def hashCode = MurmurHash3.wrappedArrayHash(array)
+ override def equals(that: Any) = that match {
+ case that: ofChar => Arrays.equals(array, that.array)
+ case _ => super.equals(that)
+ }
}
final class ofInt(val array: Array[Int]) extends WrappedArray[Int] with Serializable {
@@ -154,6 +177,11 @@ object WrappedArray {
def length: Int = array.length
def apply(index: Int): Int = array(index)
def update(index: Int, elem: Int) { array(index) = elem }
+ override def hashCode = MurmurHash3.wrappedArrayHash(array)
+ override def equals(that: Any) = that match {
+ case that: ofInt => Arrays.equals(array, that.array)
+ case _ => super.equals(that)
+ }
}
final class ofLong(val array: Array[Long]) extends WrappedArray[Long] with Serializable {
@@ -161,6 +189,11 @@ object WrappedArray {
def length: Int = array.length
def apply(index: Int): Long = array(index)
def update(index: Int, elem: Long) { array(index) = elem }
+ override def hashCode = MurmurHash3.wrappedArrayHash(array)
+ override def equals(that: Any) = that match {
+ case that: ofLong => Arrays.equals(array, that.array)
+ case _ => super.equals(that)
+ }
}
final class ofFloat(val array: Array[Float]) extends WrappedArray[Float] with Serializable {
@@ -168,6 +201,11 @@ object WrappedArray {
def length: Int = array.length
def apply(index: Int): Float = array(index)
def update(index: Int, elem: Float) { array(index) = elem }
+ override def hashCode = MurmurHash3.wrappedArrayHash(array)
+ override def equals(that: Any) = that match {
+ case that: ofFloat => Arrays.equals(array, that.array)
+ case _ => super.equals(that)
+ }
}
final class ofDouble(val array: Array[Double]) extends WrappedArray[Double] with Serializable {
@@ -175,6 +213,11 @@ object WrappedArray {
def length: Int = array.length
def apply(index: Int): Double = array(index)
def update(index: Int, elem: Double) { array(index) = elem }
+ override def hashCode = MurmurHash3.wrappedArrayHash(array)
+ override def equals(that: Any) = that match {
+ case that: ofDouble => Arrays.equals(array, that.array)
+ case _ => super.equals(that)
+ }
}
final class ofBoolean(val array: Array[Boolean]) extends WrappedArray[Boolean] with Serializable {
@@ -182,6 +225,11 @@ object WrappedArray {
def length: Int = array.length
def apply(index: Int): Boolean = array(index)
def update(index: Int, elem: Boolean) { array(index) = elem }
+ override def hashCode = MurmurHash3.wrappedArrayHash(array)
+ override def equals(that: Any) = that match {
+ case that: ofBoolean => Arrays.equals(array, that.array)
+ case _ => super.equals(that)
+ }
}
final class ofUnit(val array: Array[Unit]) extends WrappedArray[Unit] with Serializable {
@@ -189,5 +237,10 @@ object WrappedArray {
def length: Int = array.length
def apply(index: Int): Unit = array(index)
def update(index: Int, elem: Unit) { array(index) = elem }
+ override def hashCode = MurmurHash3.wrappedArrayHash(array)
+ override def equals(that: Any) = that match {
+ case that: ofUnit => array.length == that.array.length
+ case _ => super.equals(that)
+ }
}
}
diff --git a/src/library/scala/collection/mutable/WrappedArrayBuilder.scala b/src/library/scala/collection/mutable/WrappedArrayBuilder.scala
index 5781ec91be..5bc5811450 100644
--- a/src/library/scala/collection/mutable/WrappedArrayBuilder.scala
+++ b/src/library/scala/collection/mutable/WrappedArrayBuilder.scala
@@ -13,16 +13,17 @@ package collection
package mutable
import scala.reflect.ClassTag
-import scala.runtime.ScalaRunTime._
/** A builder class for arrays.
*
+ * This builder can be reused.
+ *
* @tparam A type of elements that can be added to this builder.
* @param tag class tag for objects of type `A`.
*
* @since 2.8
*/
-class WrappedArrayBuilder[A](tag: ClassTag[A]) extends Builder[A, WrappedArray[A]] {
+class WrappedArrayBuilder[A](tag: ClassTag[A]) extends ReusableBuilder[A, WrappedArray[A]] {
@deprecated("use tag instead", "2.10.0")
val manifest: ClassTag[A] = tag
@@ -32,7 +33,7 @@ class WrappedArrayBuilder[A](tag: ClassTag[A]) extends Builder[A, WrappedArray[A
private var size: Int = 0
private def mkArray(size: Int): WrappedArray[A] = {
- val runtimeClass = arrayElementClass(tag)
+ val runtimeClass = tag.runtimeClass
val newelems = runtimeClass match {
case java.lang.Byte.TYPE => new WrappedArray.ofByte(new Array[Byte](size)).asInstanceOf[WrappedArray[A]]
case java.lang.Short.TYPE => new WrappedArray.ofShort(new Array[Short](size)).asInstanceOf[WrappedArray[A]]
@@ -73,9 +74,7 @@ class WrappedArrayBuilder[A](tag: ClassTag[A]) extends Builder[A, WrappedArray[A
this
}
- def clear() {
- size = 0
- }
+ def clear() { size = 0 }
def result() = {
if (capacity != 0 && capacity == size) {
diff --git a/src/library/scala/collection/package.scala b/src/library/scala/collection/package.scala
index 856f901b77..6df254c0e0 100644
--- a/src/library/scala/collection/package.scala
+++ b/src/library/scala/collection/package.scala
@@ -76,13 +76,9 @@ package scala
* The concrete parallel collections also have specific performance characteristics which are
* described in [[http://docs.scala-lang.org/overviews/parallel-collections/concrete-parallel-collections.html#performance-characteristics the parallel collections guide]]
*
- * === Converting between Java Collections ===
+ * === Converting to and from Java Collections ===
*
- * The [[scala.collection.JavaConversions]] object provides implicit defs that
- * will allow mostly seamless integration between APIs using Java Collections
- * and the Scala collections library.
- *
- * Alternatively the [[scala.collection.JavaConverters]] object provides a collection
+ * The [[scala.collection.JavaConverters]] object provides a collection
* of decorators that allow converting between Scala and Java collections using `asScala`
* and `asJava` methods.
*/
diff --git a/src/library/scala/collection/parallel/ParIterableLike.scala b/src/library/scala/collection/parallel/ParIterableLike.scala
index 8c9b959569..2e60089df5 100644
--- a/src/library/scala/collection/parallel/ParIterableLike.scala
+++ b/src/library/scala/collection/parallel/ParIterableLike.scala
@@ -9,6 +9,8 @@
package scala
package collection.parallel
+import scala.language.{ higherKinds, implicitConversions }
+
import scala.collection.mutable.Builder
import scala.collection.mutable.ArrayBuffer
import scala.collection.IterableLike
@@ -21,13 +23,9 @@ import scala.collection.GenIterable
import scala.collection.GenTraversableOnce
import scala.collection.GenTraversable
import immutable.HashMapCombiner
-import scala.reflect.{ClassTag, classTag}
-
-import java.util.concurrent.atomic.AtomicBoolean
+import scala.reflect.ClassTag
import scala.annotation.unchecked.uncheckedVariance
-import scala.annotation.unchecked.uncheckedStable
-import scala.language.{ higherKinds, implicitConversions }
import scala.collection.parallel.ParallelCollectionImplicits._
@@ -195,7 +193,7 @@ self: ParIterableLike[T, Repr, Sequential] =>
* import scala.collection.parallel._
* val pc = mutable.ParArray(1, 2, 3)
* pc.tasksupport = new ForkJoinTaskSupport(
- * new scala.concurrent.forkjoin.ForkJoinPool(2))
+ * new java.util.concurrent.ForkJoinPool(2))
* }}}
*
* @see [[scala.collection.parallel.TaskSupport]]
@@ -844,7 +842,7 @@ self: ParIterableLike[T, Repr, Sequential] =>
tasksupport.executeAndWaitResult(new ToParMap(combinerFactory(cbf), splitter)(ev) mapResult { _.resultWithTaskSupport })
}
- @deprecated("Use .seq.view instead", "2.11.0")
+ @deprecated("use .seq.view instead", "2.11.0")
def view = seq.view
override def toArray[U >: T: ClassTag]: Array[U] = {
@@ -1284,7 +1282,7 @@ self: ParIterableLike[T, Repr, Sequential] =>
extends Transformer[Combiner[(U, S), That], Zip[U, S, That]] {
@volatile var result: Result = null
def leaf(prev: Option[Result]) = result = pit.zip2combiner[U, S, That](othpit, pbf())
- protected[this] def newSubtask(p: IterableSplitter[T]) = unsupported
+ protected[this] def newSubtask(p: IterableSplitter[T]) = throw new UnsupportedOperationException
override def split = {
val pits = pit.splitWithSignalling
val sizes = pits.map(_.remaining)
@@ -1300,7 +1298,7 @@ self: ParIterableLike[T, Repr, Sequential] =>
extends Transformer[Combiner[(U, S), That], ZipAll[U, S, That]] {
@volatile var result: Result = null
def leaf(prev: Option[Result]) = result = pit.zipAll2combiner[U, S, That](othpit, thiselem, thatelem, pbf())
- protected[this] def newSubtask(p: IterableSplitter[T]) = unsupported
+ protected[this] def newSubtask(p: IterableSplitter[T]) = throw new UnsupportedOperationException
override def split = if (pit.remaining <= len) {
val pits = pit.splitWithSignalling
val sizes = pits.map(_.remaining)
@@ -1322,7 +1320,7 @@ self: ParIterableLike[T, Repr, Sequential] =>
extends Accessor[Unit, CopyToArray[U, This]] {
@volatile var result: Unit = ()
def leaf(prev: Option[Unit]) = pit.copyToArray(array, from, len)
- protected[this] def newSubtask(p: IterableSplitter[T]) = unsupported
+ protected[this] def newSubtask(p: IterableSplitter[T]) = throw new UnsupportedOperationException
override def split = {
val pits = pit.splitWithSignalling
for ((p, untilp) <- pits zip pits.scanLeft(0)(_ + _.remaining); if untilp < len) yield {
@@ -1379,7 +1377,7 @@ self: ParIterableLike[T, Repr, Sequential] =>
val half = howmany / 2
ScanNode(mergeTrees(trees, from, half), mergeTrees(trees, from + half, howmany - half))
} else trees(from)
- protected[this] def newSubtask(pit: IterableSplitter[T]) = unsupported
+ protected[this] def newSubtask(pit: IterableSplitter[T]) = throw new UnsupportedOperationException
override def split = {
val pits = pit.splitWithSignalling
for ((p, untilp) <- pits zip pits.scanLeft(from)(_ + _.remaining)) yield {
@@ -1416,7 +1414,7 @@ self: ParIterableLike[T, Repr, Sequential] =>
new FromScanTree(left, z, op, cbf),
new FromScanTree(right, z, op, cbf)
)
- case _ => unsupportedop("Cannot be split further")
+ case _ => throw new UnsupportedOperationException("Cannot be split further")
}
def shouldSplitFurther = tree match {
case ScanNode(_, _) => true
diff --git a/src/library/scala/collection/parallel/ParMap.scala b/src/library/scala/collection/parallel/ParMap.scala
index 9f92e6c1e8..70afe5174b 100644
--- a/src/library/scala/collection/parallel/ParMap.scala
+++ b/src/library/scala/collection/parallel/ParMap.scala
@@ -11,7 +11,6 @@ package collection.parallel
import scala.collection.Map
import scala.collection.GenMap
-import scala.collection.mutable.Builder
import scala.collection.generic.ParMapFactory
import scala.collection.generic.GenericParMapTemplate
import scala.collection.generic.GenericParMapCompanion
diff --git a/src/library/scala/collection/parallel/ParMapLike.scala b/src/library/scala/collection/parallel/ParMapLike.scala
index 0a671fb085..a3ac388587 100644
--- a/src/library/scala/collection/parallel/ParMapLike.scala
+++ b/src/library/scala/collection/parallel/ParMapLike.scala
@@ -12,10 +12,8 @@ package collection.parallel
import scala.collection.MapLike
import scala.collection.GenMapLike
import scala.collection.Map
-import scala.collection.mutable.Builder
+
import scala.annotation.unchecked.uncheckedVariance
-import scala.collection.generic.IdleSignalling
-import scala.collection.generic.Signalling
/** A template trait for mutable parallel maps. This trait is to be mixed in
* with concrete parallel maps to override the representation type.
diff --git a/src/library/scala/collection/parallel/ParSeqLike.scala b/src/library/scala/collection/parallel/ParSeqLike.scala
index 0b6fec364e..60fa1858e7 100644
--- a/src/library/scala/collection/parallel/ParSeqLike.scala
+++ b/src/library/scala/collection/parallel/ParSeqLike.scala
@@ -9,11 +9,10 @@
package scala
package collection.parallel
-import scala.collection.{ Parallel, SeqLike, GenSeqLike, GenSeq, GenIterable, Iterator }
+import scala.collection.{ SeqLike, GenSeq, GenIterable, Iterator }
import scala.collection.generic.DefaultSignalling
import scala.collection.generic.AtomicIndexFlag
import scala.collection.generic.CanBuildFrom
-import scala.collection.generic.CanCombineFrom
import scala.collection.generic.VolatileAbort
import scala.collection.parallel.ParallelCollectionImplicits._
@@ -365,7 +364,7 @@ self =>
pit.setIndexFlagIfLesser(from)
}
}
- protected[this] def newSubtask(p: SuperParIterator) = unsupported
+ protected[this] def newSubtask(p: SuperParIterator) = throw new UnsupportedOperationException
override def split = {
val pits = pit.splitWithSignalling
for ((p, untilp) <- pits zip pits.scanLeft(from)(_ + _.remaining)) yield new IndexWhere(pred, untilp, p)
@@ -386,7 +385,7 @@ self =>
pit.setIndexFlagIfGreater(pos)
}
}
- protected[this] def newSubtask(p: SuperParIterator) = unsupported
+ protected[this] def newSubtask(p: SuperParIterator) = throw new UnsupportedOperationException
override def split = {
val pits = pit.splitWithSignalling
for ((p, untilp) <- pits zip pits.scanLeft(pos)(_ + _.remaining)) yield new LastIndexWhere(pred, untilp, p)
@@ -420,7 +419,7 @@ self =>
result = pit.sameElements(otherpit)
if (!result) pit.abort()
}
- protected[this] def newSubtask(p: SuperParIterator) = unsupported
+ protected[this] def newSubtask(p: SuperParIterator) = throw new UnsupportedOperationException
override def split = {
val fp = pit.remaining / 2
val sp = pit.remaining - fp
@@ -434,7 +433,7 @@ self =>
extends Transformer[Combiner[U, That], Updated[U, That]] {
@volatile var result: Combiner[U, That] = null
def leaf(prev: Option[Combiner[U, That]]) = result = pit.updated2combiner(pos, elem, pbf())
- protected[this] def newSubtask(p: SuperParIterator) = unsupported
+ protected[this] def newSubtask(p: SuperParIterator) = throw new UnsupportedOperationException
override def split = {
val pits = pit.splitWithSignalling
for ((p, untilp) <- pits zip pits.scanLeft(0)(_ + _.remaining)) yield new Updated(pos - untilp, elem, pbf, p)
@@ -447,7 +446,7 @@ self =>
extends Transformer[Combiner[(U, S), That], Zip[U, S, That]] {
@volatile var result: Result = null
def leaf(prev: Option[Result]) = result = pit.zip2combiner[U, S, That](otherpit, cf())
- protected[this] def newSubtask(p: SuperParIterator) = unsupported
+ protected[this] def newSubtask(p: SuperParIterator) = throw new UnsupportedOperationException
override def split = {
val fp = len / 2
val sp = len - len / 2
@@ -468,7 +467,7 @@ self =>
result = pit.corresponds(corr)(otherpit)
if (!result) pit.abort()
}
- protected[this] def newSubtask(p: SuperParIterator) = unsupported
+ protected[this] def newSubtask(p: SuperParIterator) = throw new UnsupportedOperationException
override def split = {
val fp = pit.remaining / 2
val sp = pit.remaining - fp
diff --git a/src/library/scala/collection/parallel/RemainsIterator.scala b/src/library/scala/collection/parallel/RemainsIterator.scala
index 5f2ceac0e0..63d63d9ef3 100644
--- a/src/library/scala/collection/parallel/RemainsIterator.scala
+++ b/src/library/scala/collection/parallel/RemainsIterator.scala
@@ -9,13 +9,10 @@
package scala
package collection.parallel
-import scala.collection.Parallel
import scala.collection.generic.Signalling
import scala.collection.generic.DelegatedSignalling
import scala.collection.generic.IdleSignalling
-import scala.collection.generic.CanCombineFrom
import scala.collection.mutable.Builder
-import scala.collection.Iterator.empty
import scala.collection.GenTraversableOnce
import scala.collection.parallel.immutable.repetition
@@ -456,6 +453,15 @@ self =>
}
it
}
+ /** Drop implemented as simple eager consumption. */
+ override def drop(n: Int): IterableSplitter[T] = {
+ var i = 0
+ while (i < n && hasNext) {
+ next()
+ i += 1
+ }
+ this
+ }
override def take(n: Int): IterableSplitter[T] = newTaken(n)
override def slice(from1: Int, until1: Int): IterableSplitter[T] = newSliceInternal(newTaken(until1), from1)
diff --git a/src/library/scala/collection/parallel/TaskSupport.scala b/src/library/scala/collection/parallel/TaskSupport.scala
index 9064018d46..4d633253ce 100644
--- a/src/library/scala/collection/parallel/TaskSupport.scala
+++ b/src/library/scala/collection/parallel/TaskSupport.scala
@@ -10,13 +10,13 @@ package scala
package collection.parallel
import java.util.concurrent.ThreadPoolExecutor
-import scala.concurrent.forkjoin.ForkJoinPool
+import java.util.concurrent.ForkJoinPool
import scala.concurrent.ExecutionContext
/** A trait implementing the scheduling of a parallel collection operation.
*
* Parallel collections are modular in the way operations are scheduled. Each
- * parallel collection is parametrized with a task support object which is
+ * parallel collection is parameterized with a task support object which is
* responsible for scheduling and load-balancing tasks to processors.
*
* A task support object can be changed in a parallel collection after it has
@@ -41,7 +41,7 @@ import scala.concurrent.ExecutionContext
* import scala.collection.parallel._
* val pc = mutable.ParArray(1, 2, 3)
* pc.tasksupport = new ForkJoinTaskSupport(
- * new scala.concurrent.forkjoin.ForkJoinPool(2))
+ * new java.util.concurrent.ForkJoinPool(2))
* }}}
*
* @see [[http://docs.scala-lang.org/overviews/parallel-collections/configuration.html Configuring Parallel Collections]] section
@@ -60,7 +60,7 @@ extends TaskSupport with AdaptiveWorkStealingForkJoinTasks
*
* @see [[scala.collection.parallel.TaskSupport]] for more information.
*/
-@deprecated("Use `ForkJoinTaskSupport` instead.", "2.11.0")
+@deprecated("use `ForkJoinTaskSupport` instead", "2.11.0")
class ThreadPoolTaskSupport(val environment: ThreadPoolExecutor = ThreadPoolTasks.defaultThreadPool)
extends TaskSupport with AdaptiveWorkStealingThreadPoolTasks
@@ -71,7 +71,7 @@ extends TaskSupport with AdaptiveWorkStealingThreadPoolTasks
* forkjoin based task support or a thread pool executor one, depending on
* what the execution context uses.
*
- * By default, parallel collections are parametrized with this task support
+ * By default, parallel collections are parameterized with this task support
* object, so parallel collections share the same execution context backend
* as the rest of the `scala.concurrent` package.
*
diff --git a/src/library/scala/collection/parallel/Tasks.scala b/src/library/scala/collection/parallel/Tasks.scala
index fcf0dff846..f472c6be5c 100644
--- a/src/library/scala/collection/parallel/Tasks.scala
+++ b/src/library/scala/collection/parallel/Tasks.scala
@@ -10,7 +10,7 @@ package scala
package collection.parallel
import java.util.concurrent.ThreadPoolExecutor
-import scala.concurrent.forkjoin._
+import java.util.concurrent.{ForkJoinPool, RecursiveAction, ForkJoinWorkerThread}
import scala.concurrent.ExecutionContext
import scala.util.control.Breaks._
import scala.annotation.unchecked.uncheckedVariance
@@ -66,13 +66,10 @@ trait Task[R, +Tp] {
}
private[parallel] def mergeThrowables(that: Task[_, _]) {
- // TODO: As soon as we target Java >= 7, use Throwable#addSuppressed
- // to pass additional Throwables to the caller, e. g.
- // if (this.throwable != null && that.throwable != null)
- // this.throwable.addSuppressed(that.throwable)
- // For now, we just use whatever Throwable comes across “first”.
- if (this.throwable == null && that.throwable != null)
- this.throwable = that.throwable
+ if (this.throwable != null && that.throwable != null)
+ this.throwable.addSuppressed(that.throwable)
+ else if (this.throwable == null && that.throwable != null)
+ this.throwable = that.throwable
}
// override in concrete task implementations to signal abort to other tasks
@@ -211,7 +208,7 @@ trait AdaptiveWorkStealingTasks extends Tasks {
/** An implementation of tasks objects based on the Java thread pooling API. */
-@deprecated("Use `ForkJoinTasks` instead.", "2.11.0")
+@deprecated("use `ForkJoinTasks` instead", "2.11.0")
trait ThreadPoolTasks extends Tasks {
import java.util.concurrent._
@@ -320,7 +317,7 @@ trait ThreadPoolTasks extends Tasks {
}
-@deprecated("Use `ForkJoinTasks` instead.", "2.11.0")
+@deprecated("use `ForkJoinTasks` instead", "2.11.0")
object ThreadPoolTasks {
import java.util.concurrent._
@@ -448,7 +445,7 @@ trait AdaptiveWorkStealingForkJoinTasks extends ForkJoinTasks with AdaptiveWorkS
def newWrappedTask[R, Tp](b: Task[R, Tp]) = new WrappedTask[R, Tp](b)
}
-@deprecated("Use `AdaptiveWorkStealingForkJoinTasks` instead.", "2.11.0")
+@deprecated("use `AdaptiveWorkStealingForkJoinTasks` instead", "2.11.0")
trait AdaptiveWorkStealingThreadPoolTasks extends ThreadPoolTasks with AdaptiveWorkStealingTasks {
class WrappedTask[R, Tp](val body: Task[R, Tp])
@@ -526,7 +523,7 @@ private[parallel] final class FutureTasks(executor: ExecutionContext) extends Ta
}
/** This tasks implementation uses execution contexts to spawn a parallel computation.
- *
+ *
* As an optimization, it internally checks whether the execution context is the
* standard implementation based on fork/join pools, and if it is, creates a
* `ForkJoinTaskSupport` that shares the same pool to forward its request to it.
@@ -540,7 +537,7 @@ trait ExecutionContextTasks extends Tasks {
val environment: ExecutionContext
/** A driver serves as a target for this proxy `Tasks` object.
- *
+ *
* If the execution context has the standard implementation and uses fork/join pools,
* the driver is `ForkJoinTaskSupport` with the same pool, as an optimization.
* Otherwise, the driver will be a Scala `Future`-based implementation.
diff --git a/src/library/scala/collection/parallel/immutable/ParHashSet.scala b/src/library/scala/collection/parallel/immutable/ParHashSet.scala
index 65a632470e..3a1ec7fff8 100644
--- a/src/library/scala/collection/parallel/immutable/ParHashSet.scala
+++ b/src/library/scala/collection/parallel/immutable/ParHashSet.scala
@@ -197,7 +197,7 @@ extends scala.collection.parallel.BucketCombiner[T, ParHashSet[T], Any, HashSetC
while (i < chunksz) {
val v = chunkarr(i).asInstanceOf[T]
val hc = trie.computeHash(v)
- trie = trie.updated0(v, hc, rootbits)
+ trie = trie.updated0(v, hc, rootbits) // internal API, private[collection]
i += 1
}
i = 0
diff --git a/src/library/scala/collection/parallel/immutable/ParMap.scala b/src/library/scala/collection/parallel/immutable/ParMap.scala
index 2956c2a883..65bb2e12c5 100644
--- a/src/library/scala/collection/parallel/immutable/ParMap.scala
+++ b/src/library/scala/collection/parallel/immutable/ParMap.scala
@@ -16,7 +16,6 @@ import scala.collection.generic.GenericParMapCompanion
import scala.collection.generic.CanCombineFrom
import scala.collection.parallel.ParMapLike
import scala.collection.parallel.Combiner
-import scala.collection.GenMapLike
/** A template trait for immutable parallel maps.
*
diff --git a/src/library/scala/collection/parallel/immutable/ParRange.scala b/src/library/scala/collection/parallel/immutable/ParRange.scala
index ec90de3a7d..de2b53a6c0 100644
--- a/src/library/scala/collection/parallel/immutable/ParRange.scala
+++ b/src/library/scala/collection/parallel/immutable/ParRange.scala
@@ -12,7 +12,6 @@ package collection.parallel.immutable
import scala.collection.immutable.Range
import scala.collection.parallel.Combiner
import scala.collection.parallel.SeqSplitter
-import scala.collection.generic.CanCombineFrom
import scala.collection.Iterator
/** Parallel ranges.
@@ -108,6 +107,7 @@ self =>
}
}
+ override def toString = s"Par$range"
}
object ParRange {
diff --git a/src/library/scala/collection/parallel/immutable/package.scala b/src/library/scala/collection/parallel/immutable/package.scala
index 8fd84eaf4d..3cafdba5f7 100644
--- a/src/library/scala/collection/parallel/immutable/package.scala
+++ b/src/library/scala/collection/parallel/immutable/package.scala
@@ -20,7 +20,12 @@ package immutable {
self =>
def apply(idx: Int) = if (0 <= idx && idx < length) elem else throw new IndexOutOfBoundsException("" + idx)
- override def seq = throw new UnsupportedOperationException
+ override def seq: collection.immutable.Seq[T] = new collection.AbstractSeq[T] with collection.immutable.Seq[T] {
+ override def length: Int = self.length
+ override def apply(idx: Int): T = self.apply(idx)
+ override def iterator: Iterator[T] = Iterator.continually(elem).take(length)
+ override def par: ParSeq[T] = self
+ }
def update(idx: Int, elem: T) = throw new UnsupportedOperationException
class ParIterator(var i: Int = 0, val until: Int = length, elem: T = self.elem) extends SeqSplitter[T] {
diff --git a/src/library/scala/collection/parallel/mutable/LazyCombiner.scala b/src/library/scala/collection/parallel/mutable/LazyCombiner.scala
index 5ab2bb81c6..cc25b5b4b2 100644
--- a/src/library/scala/collection/parallel/mutable/LazyCombiner.scala
+++ b/src/library/scala/collection/parallel/mutable/LazyCombiner.scala
@@ -30,7 +30,6 @@ trait LazyCombiner[Elem, +To, Buff <: Growable[Elem] with Sizing] extends Combin
def result: To = allocateAndCopy
def clear() = { chain.clear() }
def combine[N <: Elem, NewTo >: To](other: Combiner[N, NewTo]): Combiner[N, NewTo] = if (this ne other) {
- import language.existentials // FIXME: See SI-7750
if (other.isInstanceOf[LazyCombiner[_, _, _]]) {
val that = other.asInstanceOf[LazyCombiner[Elem, To, Buff]]
newLazyCombiner(chain ++= that.chain)
diff --git a/src/library/scala/collection/parallel/mutable/ParArray.scala b/src/library/scala/collection/parallel/mutable/ParArray.scala
index d0d022db4b..8a2cf2716a 100644
--- a/src/library/scala/collection/parallel/mutable/ParArray.scala
+++ b/src/library/scala/collection/parallel/mutable/ParArray.scala
@@ -18,7 +18,6 @@ import scala.collection.generic.GenericParCompanion
import scala.collection.generic.CanCombineFrom
import scala.collection.generic.CanBuildFrom
import scala.collection.generic.ParFactory
-import scala.collection.generic.Sizing
import scala.collection.parallel.Combiner
import scala.collection.parallel.SeqSplitter
import scala.collection.parallel.ParSeqLike
diff --git a/src/library/scala/collection/parallel/mutable/ParTrieMap.scala b/src/library/scala/collection/parallel/mutable/ParTrieMap.scala
index a1dc37cec9..2faf223b99 100644
--- a/src/library/scala/collection/parallel/mutable/ParTrieMap.scala
+++ b/src/library/scala/collection/parallel/mutable/ParTrieMap.scala
@@ -152,18 +152,9 @@ extends TrieMapIterator[K, V](lev, ct, mustInit)
/** Only used within the `ParTrieMap`. */
private[mutable] trait ParTrieMapCombiner[K, V] extends Combiner[(K, V), ParTrieMap[K, V]] {
- def combine[N <: (K, V), NewTo >: ParTrieMap[K, V]](other: Combiner[N, NewTo]): Combiner[N, NewTo] = if (this eq other) this else {
- throw new UnsupportedOperationException("This shouldn't have been called in the first place.")
-
- val thiz = this.asInstanceOf[ParTrieMap[K, V]]
- val that = other.asInstanceOf[ParTrieMap[K, V]]
- val result = new ParTrieMap[K, V]
-
- result ++= thiz.iterator
- result ++= that.iterator
-
- result
- }
+ def combine[N <: (K, V), NewTo >: ParTrieMap[K, V]](other: Combiner[N, NewTo]): Combiner[N, NewTo] =
+ if (this eq other) this
+ else throw new UnsupportedOperationException("This shouldn't have been called in the first place.")
override def canBeShared = true
}
diff --git a/src/library/scala/collection/parallel/mutable/ResizableParArrayCombiner.scala b/src/library/scala/collection/parallel/mutable/ResizableParArrayCombiner.scala
index 79322c85b1..6883457fef 100644
--- a/src/library/scala/collection/parallel/mutable/ResizableParArrayCombiner.scala
+++ b/src/library/scala/collection/parallel/mutable/ResizableParArrayCombiner.scala
@@ -9,18 +9,10 @@
package scala
package collection.parallel.mutable
-
-
-import scala.collection.generic.Sizing
import scala.collection.mutable.ArraySeq
import scala.collection.mutable.ArrayBuffer
-import scala.collection.parallel.TaskSupport
-import scala.collection.parallel.unsupportedop
-import scala.collection.parallel.Combiner
import scala.collection.parallel.Task
-
-
/** An array combiner that uses a chain of arraybuffers to store elements. */
trait ResizableParArrayCombiner[T] extends LazyCombiner[T, ParArray[T], ExposedArrayBuffer[T]] {
diff --git a/src/library/scala/collection/parallel/mutable/UnrolledParArrayCombiner.scala b/src/library/scala/collection/parallel/mutable/UnrolledParArrayCombiner.scala
index d1379cde11..e71e61f2f1 100644
--- a/src/library/scala/collection/parallel/mutable/UnrolledParArrayCombiner.scala
+++ b/src/library/scala/collection/parallel/mutable/UnrolledParArrayCombiner.scala
@@ -9,23 +9,11 @@
package scala
package collection.parallel.mutable
-import scala.collection.generic.Sizing
import scala.collection.mutable.ArraySeq
-import scala.collection.mutable.ArrayBuffer
-import scala.collection.mutable.UnrolledBuffer
+import scala.collection.mutable.DoublingUnrolledBuffer
import scala.collection.mutable.UnrolledBuffer.Unrolled
-import scala.collection.parallel.TaskSupport
-import scala.collection.parallel.unsupportedop
import scala.collection.parallel.Combiner
import scala.collection.parallel.Task
-import scala.reflect.ClassTag
-
-// Todo -- revisit whether inheritance is the best way to achieve this functionality
-private[mutable] class DoublingUnrolledBuffer[T](implicit t: ClassTag[T]) extends UnrolledBuffer[T]()(t) {
- override def calcNextLength(sz: Int) = if (sz < 10000) sz * 2 else sz
- protected override def newUnrolled = new Unrolled[T](0, new Array[T](4), null, this)
-}
-
/** An array combiner that uses doubling unrolled buffers to store elements. */
trait UnrolledParArrayCombiner[T]
@@ -62,7 +50,7 @@ extends Combiner[T, ParArray[T]] {
case that: UnrolledParArrayCombiner[t] =>
buff concat that.buff
this
- case _ => unsupportedop("Cannot combine with combiner of different type.")
+ case _ => throw new UnsupportedOperationException("Cannot combine with combiner of different type.")
}
def size = buff.size
diff --git a/src/library/scala/collection/parallel/package.scala b/src/library/scala/collection/parallel/package.scala
index d77dcb0658..eaa87b675a 100644
--- a/src/library/scala/collection/parallel/package.scala
+++ b/src/library/scala/collection/parallel/package.scala
@@ -35,15 +35,7 @@ package object parallel {
else sz
}
- private[parallel] def unsupported = throw new UnsupportedOperationException
-
- private[parallel] def unsupportedop(msg: String) = throw new UnsupportedOperationException(msg)
-
- private[parallel] def outofbounds(idx: Int) = throw new IndexOutOfBoundsException(idx.toString)
-
- private[parallel] def getTaskSupport: TaskSupport = new ExecutionContextTaskSupport
-
- val defaultTaskSupport: TaskSupport = getTaskSupport
+ val defaultTaskSupport: TaskSupport = new ExecutionContextTaskSupport
def setTaskSupport[Coll](c: Coll, t: TaskSupport): Coll = {
c match {
@@ -98,7 +90,7 @@ package parallel {
}
}
}
-
+
trait FactoryOps[From, Elem, To] {
trait Otherwise[R] {
def otherwise(notbody: => R): R
@@ -122,9 +114,9 @@ package parallel {
def ifParSeq[R](isbody: ParSeq[T] => R): Otherwise[R]
}
- @deprecated("This trait will be removed.", "2.11.0")
+ @deprecated("this trait will be removed", "2.11.0")
trait ThrowableOps {
- @deprecated("This method will be removed.", "2.11.0")
+ @deprecated("this method will be removed", "2.11.0")
def alongWith(that: Throwable): Throwable
}
@@ -143,7 +135,7 @@ package parallel {
}
/** Composite throwable - thrown when multiple exceptions are thrown at the same time. */
- @deprecated("This class will be removed.", "2.11.0")
+ @deprecated("this class will be removed.", "2.11.0")
final case class CompositeThrowable(throwables: Set[Throwable]) extends Exception(
"Multiple exceptions thrown during a parallel computation: " +
throwables.map(t => t + "\n" + t.getStackTrace.take(10).++("...").mkString("\n")).mkString("\n\n")
diff --git a/src/library/scala/collection/script/Location.scala b/src/library/scala/collection/script/Location.scala
index bed74bf9ca..8a0b10c331 100644
--- a/src/library/scala/collection/script/Location.scala
+++ b/src/library/scala/collection/script/Location.scala
@@ -18,17 +18,17 @@ package script
* @since 2.8
*/
-@deprecated("Scripting is deprecated.", "2.11.0")
+@deprecated("scripting is deprecated", "2.11.0")
sealed abstract class Location
-@deprecated("Scripting is deprecated.", "2.11.0")
+@deprecated("scripting is deprecated", "2.11.0")
case object Start extends Location
-@deprecated("Scripting is deprecated.", "2.11.0")
+@deprecated("scripting is deprecated", "2.11.0")
case object End extends Location
-@deprecated("Scripting is deprecated.", "2.11.0")
+@deprecated("scripting is deprecated", "2.11.0")
case object NoLo extends Location
-@deprecated("Scripting is deprecated.", "2.11.0")
+@deprecated("scripting is deprecated", "2.11.0")
case class Index(n: Int) extends Location
diff --git a/src/library/scala/collection/script/Message.scala b/src/library/scala/collection/script/Message.scala
index 3fc2a0ec7e..a6ba9d9523 100644
--- a/src/library/scala/collection/script/Message.scala
+++ b/src/library/scala/collection/script/Message.scala
@@ -21,7 +21,7 @@ import mutable.ArrayBuffer
* @version 1.0, 08/07/2003
* @since 2.8
*/
-@deprecated("Scripting is deprecated.", "2.11.0")
+@deprecated("scripting is deprecated", "2.11.0")
trait Message[+A]
/** This observable update refers to inclusion operations that add new elements
@@ -30,7 +30,7 @@ trait Message[+A]
* @author Matthias Zenger
* @version 1.0, 08/07/2003
*/
-@deprecated("Scripting is deprecated.", "2.11.0")
+@deprecated("scripting is deprecated", "2.11.0")
case class Include[+A](location: Location, elem: A) extends Message[A] {
def this(elem: A) = this(NoLo, elem)
}
@@ -41,7 +41,7 @@ case class Include[+A](location: Location, elem: A) extends Message[A] {
* @author Matthias Zenger
* @version 1.0, 08/07/2003
*/
-@deprecated("Scripting is deprecated.", "2.11.0")
+@deprecated("scripting is deprecated", "2.11.0")
case class Update[+A](location: Location, elem: A) extends Message[A] {
def this(elem: A) = this(NoLo, elem)
}
@@ -52,7 +52,7 @@ case class Update[+A](location: Location, elem: A) extends Message[A] {
* @author Matthias Zenger
* @version 1.0, 08/07/2003
*/
-@deprecated("Scripting is deprecated.", "2.11.0")
+@deprecated("scripting is deprecated", "2.11.0")
case class Remove[+A](location: Location, elem: A) extends Message[A] {
def this(elem: A) = this(NoLo, elem)
}
@@ -62,7 +62,7 @@ case class Remove[+A](location: Location, elem: A) extends Message[A] {
* @author Matthias Zenger
* @version 1.0, 08/07/2003
*/
-@deprecated("Scripting is deprecated.", "2.11.0")
+@deprecated("scripting is deprecated", "2.11.0")
case class Reset[+A]() extends Message[A]
/** Objects of this class represent compound messages consisting
@@ -71,7 +71,7 @@ case class Reset[+A]() extends Message[A]
* @author Matthias Zenger
* @version 1.0, 10/05/2004
*/
-@deprecated("Scripting is deprecated.", "2.11.0")
+@deprecated("scripting is deprecated", "2.11.0")
class Script[A] extends ArrayBuffer[Message[A]] with Message[A] {
override def toString(): String = {
diff --git a/src/library/scala/collection/script/Scriptable.scala b/src/library/scala/collection/script/Scriptable.scala
index 4db75ddd3e..8965286b0d 100644
--- a/src/library/scala/collection/script/Scriptable.scala
+++ b/src/library/scala/collection/script/Scriptable.scala
@@ -17,7 +17,7 @@ package script
* @version 1.0, 09/05/2004
* @since 2.8
*/
-@deprecated("Scripting is deprecated.", "2.11.0")
+@deprecated("scripting is deprecated", "2.11.0")
trait Scriptable[A] {
/** Send a message to this scriptable object.
*/