Skip to content

Commit

Permalink
further optimize Chain#distinctBy
Browse files Browse the repository at this point in the history
  • Loading branch information
satorg committed Apr 2, 2022
1 parent 2c895ff commit 0f8e118
Showing 1 changed file with 19 additions and 11 deletions.
30 changes: 19 additions & 11 deletions core/src/main/scala/cats/data/Chain.scala
Original file line number Diff line number Diff line change
Expand Up @@ -123,13 +123,19 @@ sealed abstract class Chain[+A] {
/**
* Returns true if there are no elements in this collection.
*/
def isEmpty: Boolean = !this.isInstanceOf[Chain.NonEmpty[_]]
def isEmpty: Boolean = this eq Chain.Empty

/**
* Returns false if there are no elements in this collection.
*/
final def nonEmpty: Boolean = !isEmpty

// Temporary solution for length comparison in some special cases.
// TODO: Consider implementing more generic `lengthCompare` method.
private def isEmptyOrSingleton: Boolean =
// Chain.Append and Chain.Wrap always contain more than one element.
isEmpty || this.isInstanceOf[Chain.Singleton[_]]

/**
* Concatenates this with `c` in O(1) runtime.
*/
Expand Down Expand Up @@ -642,17 +648,19 @@ sealed abstract class Chain[+A] {
* }}}
*/
def distinctBy[B](f: A => B)(implicit O: Order[B]): Chain[A] = {
implicit val ord: Ordering[B] = O.toOrdering

val alreadyIn = mutable.TreeSet.empty[B]

foldLeft(Chain.empty[A]) { (elementsSoFar, a) =>
val b = f(a)
if (alreadyIn.add(b)) {
elementsSoFar :+ a
} else {
elementsSoFar
if (isEmptyOrSingleton) this
else {
implicit val ord: Ordering[B] = O.toOrdering

var result = Chain.empty[A]
val seen = mutable.TreeSet.empty[B]
val it = iterator
while (it.hasNext) {
val next = it.next()
if (seen.add(f(next)))
result ++= one(next)
}
result
}
}

Expand Down

0 comments on commit 0f8e118

Please sign in to comment.