Search code examples
scalacomparatorpriority-queue

scala.collection.mutable.PriorityQueue: Comparing with 2 or more attributes of a case class


This question Easy idiomatic way to define Ordering for a simple case class looks similar but not same. This question is more related to priority queue.

import scala.collection.mutable.PriorityQueue

  case class Task(prio: Int, text: String, jobPriority:Int)
    extends Ordered[Task] {
    def compare(that: Task) = that.prio compare this.prio
   // def compare(x: Task, y: Task) = y.prio compare this.prio //&&  y.jobPriority compare this.jobPriority

  }

  //test
  var q: mutable.PriorityQueue[Task] = PriorityQueue[Task]() ++ Seq(Task(3, "Clear drains",1), Task(4, "Feed cat",2),
    Task(5, "Make tea",9), Task(1, "Solve RC tasks",5), Task(2, "Tax return",5))
  while (q.nonEmpty) println(q dequeue)

is giving me this output :

Task(1,Solve RC tasks,5)
Task(2,Tax return,5)
Task(3,Clear drains,1)
Task(4,Feed cat,2)
Task(5,Make tea,9)

now I want to consider jobPriority as well while doing comparison. just like custom java comparator which compares multiple attributes.

Is there any way in scala to achieve this ?


Solution

  • You can do something like this:

    case class Task(prio: Int, text: String, jobPriority:Int)
        extends Ordered[Task] {
        def prioCompare(that: Task) = that.prio compare this.prio
        def jobPriorityCompare(that: Task) = that.jobPriority compare this.jobPriority
        def compare(that: Task) = {
          val prioC = prioCompare(that)
    
          if(prioC == 0) jobPriorityCompare(that) else prioC
        }
    
      }
    
      //test
      var q: mutable.PriorityQueue[Task] = PriorityQueue[Task]() ++ Seq(Task(3, "Clear drains",6), Task(4, "Feed cat",2),
        Task(5, "Make tea",9), Task(1, "Solve RC tasks",5), Task(3, "Tax return",5))
      while (q.nonEmpty) println(q dequeue)
    
    /* Output
    Task(1,Solve RC tasks,5)
    Task(3,Tax return,5)
    Task(3,Clear drains,6)
    Task(4,Feed cat,2)
    Task(5,Make tea,9)
    */