|
| 1 | +/* |
| 2 | + * Scala (https://www.scala-lang.org) |
| 3 | + * |
| 4 | + * Copyright EPFL and Lightbend, Inc. |
| 5 | + * |
| 6 | + * Licensed under Apache License 2.0 |
| 7 | + * (http://www.apache.org/licenses/LICENSE-2.0). |
| 8 | + * |
| 9 | + * See the NOTICE file distributed with this work for |
| 10 | + * additional information regarding copyright ownership. |
| 11 | + */ |
| 12 | + |
| 13 | +package scala.collection |
| 14 | + |
| 15 | +import scala.annotation.{implicitNotFound, nowarn} |
| 16 | +import scala.annotation.unchecked.uncheckedVariance |
| 17 | + |
| 18 | +/** Base type of sorted sets */ |
| 19 | +trait SortedSet[A] extends Set[A] |
| 20 | + with SortedSetOps[A, SortedSet, SortedSet[A]] |
| 21 | + with SortedSetFactoryDefaults[A, SortedSet, Set] { |
| 22 | + |
| 23 | + def unsorted: Set[A] = this |
| 24 | + |
| 25 | + def sortedIterableFactory: SortedIterableFactory[SortedSet] = SortedSet |
| 26 | + |
| 27 | + @nowarn("""cat=deprecation&origin=scala\.collection\.Iterable\.stringPrefix""") |
| 28 | + override protected[this] def stringPrefix: String = "SortedSet" |
| 29 | + |
| 30 | + override def equals(that: Any): Boolean = that match { |
| 31 | + case _ if this eq that.asInstanceOf[AnyRef] => true |
| 32 | + case ss: SortedSet[A @unchecked] if ss.ordering == this.ordering => |
| 33 | + (ss canEqual this) && |
| 34 | + (this.size == ss.size) && { |
| 35 | + val i1 = this.iterator |
| 36 | + val i2 = ss.iterator |
| 37 | + var allEqual = true |
| 38 | + while (allEqual && i1.hasNext) |
| 39 | + allEqual = ordering.equiv(i1.next(), i2.next()) |
| 40 | + allEqual |
| 41 | + } |
| 42 | + case _ => |
| 43 | + super.equals(that) |
| 44 | + } |
| 45 | + |
| 46 | +} |
| 47 | + |
| 48 | +trait SortedSetOps[A, +CC[X] <: SortedSet[X], +C <: SortedSetOps[A, CC, C]] |
| 49 | + extends SetOps[A, Set, C] |
| 50 | + with SortedOps[A, C] { |
| 51 | + |
| 52 | + /** The companion object of this sorted set, providing various factory methods. |
| 53 | + * |
| 54 | + * @note When implementing a custom collection type and refining `CC` to the new type, this |
| 55 | + * method needs to be overridden to return a factory for the new type (the compiler will |
| 56 | + * issue an error otherwise). |
| 57 | + */ |
| 58 | + def sortedIterableFactory: SortedIterableFactory[CC] |
| 59 | + |
| 60 | + def unsorted: Set[A] |
| 61 | + |
| 62 | + /** |
| 63 | + * Creates an iterator that contains all values from this collection |
| 64 | + * greater than or equal to `start` according to the ordering of |
| 65 | + * this collection. x.iteratorFrom(y) is equivalent to but will usually |
| 66 | + * be more efficient than x.from(y).iterator |
| 67 | + * |
| 68 | + * @param start The lower-bound (inclusive) of the iterator |
| 69 | + */ |
| 70 | + def iteratorFrom(start: A): Iterator[A] |
| 71 | + |
| 72 | + @deprecated("Use `iteratorFrom` instead.", "2.13.0") |
| 73 | + @`inline` def keysIteratorFrom(start: A): Iterator[A] = iteratorFrom(start) |
| 74 | + |
| 75 | + def firstKey: A = head |
| 76 | + def lastKey: A = last |
| 77 | + |
| 78 | + /** Find the smallest element larger than or equal to a given key. |
| 79 | + * @param key The given key. |
| 80 | + * @return `None` if there is no such node. |
| 81 | + */ |
| 82 | + def minAfter(key: A): Option[A] = rangeFrom(key).headOption |
| 83 | + |
| 84 | + /** Find the largest element less than a given key. |
| 85 | + * @param key The given key. |
| 86 | + * @return `None` if there is no such node. |
| 87 | + */ |
| 88 | + def maxBefore(key: A): Option[A] = rangeUntil(key).lastOption |
| 89 | + |
| 90 | + override def min[B >: A](implicit ord: Ordering[B]): A = |
| 91 | + if (isEmpty) throw new UnsupportedOperationException("empty.min") |
| 92 | + else if (ord == ordering) head |
| 93 | + else if (ord isReverseOf ordering) last |
| 94 | + else super.min[B] // need the type annotation for it to infer the correct implicit |
| 95 | + |
| 96 | + override def max[B >: A](implicit ord: Ordering[B]): A = |
| 97 | + if (isEmpty) throw new UnsupportedOperationException("empty.max") |
| 98 | + else if (ord == ordering) last |
| 99 | + else if (ord isReverseOf ordering) head |
| 100 | + else super.max[B] // need the type annotation for it to infer the correct implicit |
| 101 | + |
| 102 | + def rangeTo(to: A): C = { |
| 103 | + val i = rangeFrom(to).iterator |
| 104 | + if (i.isEmpty) return coll |
| 105 | + val next = i.next() |
| 106 | + if (ordering.compare(next, to) == 0) |
| 107 | + if (i.isEmpty) coll |
| 108 | + else rangeUntil(i.next()) |
| 109 | + else |
| 110 | + rangeUntil(next) |
| 111 | + } |
| 112 | + |
| 113 | + /** Builds a new sorted collection by applying a function to all elements of this $coll. |
| 114 | + * |
| 115 | + * @param f the function to apply to each element. |
| 116 | + * @tparam B the element type of the returned collection. |
| 117 | + * @return a new $coll resulting from applying the given function |
| 118 | + * `f` to each element of this $coll and collecting the results. |
| 119 | + */ |
| 120 | + def map[B](f: A => B)(implicit @implicitNotFound(SortedSetOps.ordMsg) ev: Ordering[B]): CC[B] = |
| 121 | + sortedIterableFactory.from(new View.Map(this, f)) |
| 122 | + |
| 123 | + /** Builds a new sorted collection by applying a function to all elements of this $coll |
| 124 | + * and using the elements of the resulting collections. |
| 125 | + * |
| 126 | + * @param f the function to apply to each element. |
| 127 | + * @tparam B the element type of the returned collection. |
| 128 | + * @return a new $coll resulting from applying the given collection-valued function |
| 129 | + * `f` to each element of this $coll and concatenating the results. |
| 130 | + */ |
| 131 | + def flatMap[B](f: A => IterableOnce[B])(implicit @implicitNotFound(SortedSetOps.ordMsg) ev: Ordering[B]): CC[B] = |
| 132 | + sortedIterableFactory.from(new View.FlatMap(this, f)) |
| 133 | + |
| 134 | + /** Returns a $coll formed from this $coll and another iterable collection |
| 135 | + * by combining corresponding elements in pairs. |
| 136 | + * If one of the two collections is longer than the other, its remaining elements are ignored. |
| 137 | + * |
| 138 | + * @param that The iterable providing the second half of each result pair |
| 139 | + * @tparam B the type of the second half of the returned pairs |
| 140 | + * @return a new $coll containing pairs consisting of corresponding elements of this $coll and `that`. |
| 141 | + * The length of the returned collection is the minimum of the lengths of this $coll and `that`. |
| 142 | + */ |
| 143 | + def zip[B](that: IterableOnce[B])(implicit @implicitNotFound(SortedSetOps.zipOrdMsg) ev: Ordering[(A @uncheckedVariance, B)]): CC[(A @uncheckedVariance, B)] = // sound bcs of VarianceNote |
| 144 | + sortedIterableFactory.from(that match { |
| 145 | + case that: Iterable[B] => new View.Zip(this, that) |
| 146 | + case _ => iterator.zip(that) |
| 147 | + }) |
| 148 | + |
| 149 | + /** Builds a new sorted collection by applying a partial function to all elements of this $coll |
| 150 | + * on which the function is defined. |
| 151 | + * |
| 152 | + * @param pf the partial function which filters and maps the $coll. |
| 153 | + * @tparam B the element type of the returned collection. |
| 154 | + * @return a new $coll resulting from applying the given partial function |
| 155 | + * `pf` to each element on which it is defined and collecting the results. |
| 156 | + * The order of the elements is preserved. |
| 157 | + */ |
| 158 | + def collect[B](pf: scala.PartialFunction[A, B])(implicit @implicitNotFound(SortedSetOps.ordMsg) ev: Ordering[B]): CC[B] = |
| 159 | + sortedIterableFactory.from(new View.Collect(this, pf)) |
| 160 | +} |
| 161 | + |
| 162 | +object SortedSetOps { |
| 163 | + private[collection] final val ordMsg = "No implicit Ordering[${B}] found to build a SortedSet[${B}]. You may want to upcast to a Set[${A}] first by calling `unsorted`." |
| 164 | + private[collection] final val zipOrdMsg = "No implicit Ordering[${B}] found to build a SortedSet[(${A}, ${B})]. You may want to upcast to a Set[${A}] first by calling `unsorted`." |
| 165 | + |
| 166 | + /** Specialize `WithFilter` for sorted collections |
| 167 | + * |
| 168 | + * @define coll sorted collection |
| 169 | + */ |
| 170 | + class WithFilter[+A, +IterableCC[_], +CC[X] <: SortedSet[X]]( |
| 171 | + self: SortedSetOps[A, CC, _] with IterableOps[A, IterableCC, _], |
| 172 | + p: A => Boolean |
| 173 | + ) extends IterableOps.WithFilter[A, IterableCC](self, p) { |
| 174 | + |
| 175 | + def map[B : Ordering](f: A => B): CC[B] = |
| 176 | + self.sortedIterableFactory.from(new View.Map(filtered, f)) |
| 177 | + |
| 178 | + def flatMap[B : Ordering](f: A => IterableOnce[B]): CC[B] = |
| 179 | + self.sortedIterableFactory.from(new View.FlatMap(filtered, f)) |
| 180 | + |
| 181 | + override def withFilter(q: A => Boolean): WithFilter[A, IterableCC, CC] = |
| 182 | + new WithFilter[A, IterableCC, CC](self, (a: A) => p(a) && q(a)) |
| 183 | + } |
| 184 | + |
| 185 | +} |
| 186 | + |
| 187 | +@SerialVersionUID(3L) |
| 188 | +object SortedSet extends SortedIterableFactory.Delegate[SortedSet](immutable.SortedSet) |
| 189 | + |
0 commit comments