|
| 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 |
| 14 | +package collection |
| 15 | + |
| 16 | +import scala.annotation.{implicitNotFound, nowarn} |
| 17 | + |
| 18 | +/** A Map whose keys are sorted according to a [[scala.math.Ordering]]*/ |
| 19 | +trait SortedMap[K, +V] |
| 20 | + extends Map[K, V] |
| 21 | + with SortedMapOps[K, V, SortedMap, SortedMap[K, V]] |
| 22 | + with SortedMapFactoryDefaults[K, V, SortedMap, Iterable, Map]{ |
| 23 | + |
| 24 | + def unsorted: Map[K, V] = this |
| 25 | + |
| 26 | + def sortedMapFactory: SortedMapFactory[SortedMap] = SortedMap |
| 27 | + |
| 28 | + @nowarn("""cat=deprecation&origin=scala\.collection\.Iterable\.stringPrefix""") |
| 29 | + override protected[this] def stringPrefix: String = "SortedMap" |
| 30 | + |
| 31 | + override def equals(that: Any): Boolean = that match { |
| 32 | + case _ if this eq that.asInstanceOf[AnyRef] => true |
| 33 | + case sm: SortedMap[K @unchecked, _] if sm.ordering == this.ordering => |
| 34 | + (sm canEqual this) && |
| 35 | + (this.size == sm.size) && { |
| 36 | + val i1 = this.iterator |
| 37 | + val i2 = sm.iterator |
| 38 | + var allEqual = true |
| 39 | + while (allEqual && i1.hasNext) { |
| 40 | + val kv1 = i1.next() |
| 41 | + val kv2 = i2.next() |
| 42 | + allEqual = ordering.equiv(kv1._1, kv2._1) && kv1._2 == kv2._2 |
| 43 | + } |
| 44 | + allEqual |
| 45 | + } |
| 46 | + case _ => super.equals(that) |
| 47 | + } |
| 48 | +} |
| 49 | + |
| 50 | +trait SortedMapOps[K, +V, +CC[X, Y] <: Map[X, Y] with SortedMapOps[X, Y, CC, _], +C <: SortedMapOps[K, V, CC, C]] |
| 51 | + extends MapOps[K, V, Map, C] |
| 52 | + with SortedOps[K, C] { |
| 53 | + |
| 54 | + /** The companion object of this sorted map, providing various factory methods. |
| 55 | + * |
| 56 | + * @note When implementing a custom collection type and refining `CC` to the new type, this |
| 57 | + * method needs to be overridden to return a factory for the new type (the compiler will |
| 58 | + * issue an error otherwise). |
| 59 | + */ |
| 60 | + def sortedMapFactory: SortedMapFactory[CC] |
| 61 | + |
| 62 | + /** Similar to `mapFromIterable`, but returns a SortedMap collection type. |
| 63 | + * Note that the return type is now `CC[K2, V2]`. |
| 64 | + */ |
| 65 | + @`inline` protected final def sortedMapFromIterable[K2, V2](it: Iterable[(K2, V2)])(implicit ordering: Ordering[K2]): CC[K2, V2] = sortedMapFactory.from(it) |
| 66 | + |
| 67 | + def unsorted: Map[K, V] |
| 68 | + |
| 69 | + /** |
| 70 | + * Creates an iterator over all the key/value pairs |
| 71 | + * contained in this map having a key greater than or |
| 72 | + * equal to `start` according to the ordering of |
| 73 | + * this map. x.iteratorFrom(y) is equivalent |
| 74 | + * to but often more efficient than x.from(y).iterator. |
| 75 | + * |
| 76 | + * @param start The lower bound (inclusive) |
| 77 | + * on the keys to be returned |
| 78 | + */ |
| 79 | + def iteratorFrom(start: K): Iterator[(K, V)] |
| 80 | + |
| 81 | + /** |
| 82 | + * Creates an iterator over all the keys(or elements) contained in this |
| 83 | + * collection greater than or equal to `start` |
| 84 | + * according to the ordering of this collection. x.keysIteratorFrom(y) |
| 85 | + * is equivalent to but often more efficient than |
| 86 | + * x.from(y).keysIterator. |
| 87 | + * |
| 88 | + * @param start The lower bound (inclusive) |
| 89 | + * on the keys to be returned |
| 90 | + */ |
| 91 | + def keysIteratorFrom(start: K): Iterator[K] |
| 92 | + |
| 93 | + /** |
| 94 | + * Creates an iterator over all the values contained in this |
| 95 | + * map that are associated with a key greater than or equal to `start` |
| 96 | + * according to the ordering of this map. x.valuesIteratorFrom(y) is |
| 97 | + * equivalent to but often more efficient than |
| 98 | + * x.from(y).valuesIterator. |
| 99 | + * |
| 100 | + * @param start The lower bound (inclusive) |
| 101 | + * on the keys to be returned |
| 102 | + */ |
| 103 | + def valuesIteratorFrom(start: K): Iterator[V] = iteratorFrom(start).map(_._2) |
| 104 | + |
| 105 | + def firstKey: K = head._1 |
| 106 | + def lastKey: K = last._1 |
| 107 | + |
| 108 | + /** Find the element with smallest key larger than or equal to a given key. |
| 109 | + * @param key The given key. |
| 110 | + * @return `None` if there is no such node. |
| 111 | + */ |
| 112 | + def minAfter(key: K): Option[(K, V)] = rangeFrom(key).headOption |
| 113 | + |
| 114 | + /** Find the element with largest key less than a given key. |
| 115 | + * @param key The given key. |
| 116 | + * @return `None` if there is no such node. |
| 117 | + */ |
| 118 | + def maxBefore(key: K): Option[(K, V)] = rangeUntil(key).lastOption |
| 119 | + |
| 120 | + def rangeTo(to: K): C = { |
| 121 | + val i = keySet.rangeFrom(to).iterator |
| 122 | + if (i.isEmpty) return coll |
| 123 | + val next = i.next() |
| 124 | + if (ordering.compare(next, to) == 0) |
| 125 | + if (i.isEmpty) coll |
| 126 | + else rangeUntil(i.next()) |
| 127 | + else |
| 128 | + rangeUntil(next) |
| 129 | + } |
| 130 | + |
| 131 | + override def keySet: SortedSet[K] = new KeySortedSet |
| 132 | + |
| 133 | + /** The implementation class of the set returned by `keySet` */ |
| 134 | + protected class KeySortedSet extends SortedSet[K] with GenKeySet with GenKeySortedSet { |
| 135 | + def diff(that: Set[K]): SortedSet[K] = fromSpecific(view.filterNot(that)) |
| 136 | + def rangeImpl(from: Option[K], until: Option[K]): SortedSet[K] = { |
| 137 | + val map = SortedMapOps.this.rangeImpl(from, until) |
| 138 | + new map.KeySortedSet |
| 139 | + } |
| 140 | + } |
| 141 | + |
| 142 | + /** A generic trait that is reused by sorted keyset implementations */ |
| 143 | + protected trait GenKeySortedSet extends GenKeySet { this: SortedSet[K] => |
| 144 | + implicit def ordering: Ordering[K] = SortedMapOps.this.ordering |
| 145 | + def iteratorFrom(start: K): Iterator[K] = SortedMapOps.this.keysIteratorFrom(start) |
| 146 | + } |
| 147 | + |
| 148 | + // And finally, we add new overloads taking an ordering |
| 149 | + /** Builds a new sorted map by applying a function to all elements of this $coll. |
| 150 | + * |
| 151 | + * @param f the function to apply to each element. |
| 152 | + * @return a new $coll resulting from applying the given function |
| 153 | + * `f` to each element of this $coll and collecting the results. |
| 154 | + */ |
| 155 | + def map[K2, V2](f: ((K, V)) => (K2, V2))(implicit @implicitNotFound(SortedMapOps.ordMsg) ordering: Ordering[K2]): CC[K2, V2] = |
| 156 | + sortedMapFactory.from(new View.Map[(K, V), (K2, V2)](this, f)) |
| 157 | + |
| 158 | + /** Builds a new sorted map by applying a function to all elements of this $coll |
| 159 | + * and using the elements of the resulting collections. |
| 160 | + * |
| 161 | + * @param f the function to apply to each element. |
| 162 | + * @return a new $coll resulting from applying the given collection-valued function |
| 163 | + * `f` to each element of this $coll and concatenating the results. |
| 164 | + */ |
| 165 | + def flatMap[K2, V2](f: ((K, V)) => IterableOnce[(K2, V2)])(implicit @implicitNotFound(SortedMapOps.ordMsg) ordering: Ordering[K2]): CC[K2, V2] = |
| 166 | + sortedMapFactory.from(new View.FlatMap(this, f)) |
| 167 | + |
| 168 | + /** Builds a new sorted map by applying a partial function to all elements of this $coll |
| 169 | + * on which the function is defined. |
| 170 | + * |
| 171 | + * @param pf the partial function which filters and maps the $coll. |
| 172 | + * @return a new $coll resulting from applying the given partial function |
| 173 | + * `pf` to each element on which it is defined and collecting the results. |
| 174 | + * The order of the elements is preserved. |
| 175 | + */ |
| 176 | + def collect[K2, V2](pf: PartialFunction[(K, V), (K2, V2)])(implicit @implicitNotFound(SortedMapOps.ordMsg) ordering: Ordering[K2]): CC[K2, V2] = |
| 177 | + sortedMapFactory.from(new View.Collect(this, pf)) |
| 178 | + |
| 179 | + override def concat[V2 >: V](suffix: IterableOnce[(K, V2)]): CC[K, V2] = sortedMapFactory.from(suffix match { |
| 180 | + case it: Iterable[(K, V2)] => new View.Concat(this, it) |
| 181 | + case _ => iterator.concat(suffix.iterator) |
| 182 | + })(using ordering) |
| 183 | + |
| 184 | + /** Alias for `concat` */ |
| 185 | + @`inline` override final def ++ [V2 >: V](xs: IterableOnce[(K, V2)]): CC[K, V2] = concat(xs) |
| 186 | + |
| 187 | + @deprecated("Consider requiring an immutable Map or fall back to Map.concat", "2.13.0") |
| 188 | + override def + [V1 >: V](kv: (K, V1)): CC[K, V1] = sortedMapFactory.from(new View.Appended(this, kv))(using ordering) |
| 189 | + |
| 190 | + @deprecated("Use ++ with an explicit collection argument instead of + with varargs", "2.13.0") |
| 191 | + override def + [V1 >: V](elem1: (K, V1), elem2: (K, V1), elems: (K, V1)*): CC[K, V1] = sortedMapFactory.from(new View.Concat(new View.Appended(new View.Appended(this, elem1), elem2), elems))(using ordering) |
| 192 | +} |
| 193 | + |
| 194 | +object SortedMapOps { |
| 195 | + private[collection] final val ordMsg = "No implicit Ordering[${K2}] found to build a SortedMap[${K2}, ${V2}]. You may want to upcast to a Map[${K}, ${V}] first by calling `unsorted`." |
| 196 | + |
| 197 | + /** Specializes `MapWithFilter` for sorted Map collections |
| 198 | + * |
| 199 | + * @define coll sorted map collection |
| 200 | + */ |
| 201 | + class WithFilter[K, +V, +IterableCC[_], +MapCC[X, Y] <: Map[X, Y], +CC[X, Y] <: Map[X, Y] with SortedMapOps[X, Y, CC, _]]( |
| 202 | + self: SortedMapOps[K, V, CC, _] with MapOps[K, V, MapCC, _] with IterableOps[(K, V), IterableCC, _], |
| 203 | + p: ((K, V)) => Boolean |
| 204 | + ) extends MapOps.WithFilter[K, V, IterableCC, MapCC](self, p) { |
| 205 | + |
| 206 | + def map[K2 : Ordering, V2](f: ((K, V)) => (K2, V2)): CC[K2, V2] = |
| 207 | + self.sortedMapFactory.from(new View.Map(filtered, f)) |
| 208 | + |
| 209 | + def flatMap[K2 : Ordering, V2](f: ((K, V)) => IterableOnce[(K2, V2)]): CC[K2, V2] = |
| 210 | + self.sortedMapFactory.from(new View.FlatMap(filtered, f)) |
| 211 | + |
| 212 | + override def withFilter(q: ((K, V)) => Boolean): WithFilter[K, V, IterableCC, MapCC, CC] = |
| 213 | + new WithFilter[K, V, IterableCC, MapCC, CC](self, (kv: (K, V)) => p(kv) && q(kv)) |
| 214 | + |
| 215 | + } |
| 216 | + |
| 217 | +} |
| 218 | + |
| 219 | +@SerialVersionUID(3L) |
| 220 | +object SortedMap extends SortedMapFactory.Delegate[SortedMap](immutable.SortedMap) |
0 commit comments