13

List.max returns the "largest" element of a list based on some ordering... But if the list is empty you'll get a java.lang.UnsupportedOperationException: empty.max exception. I don't really like littering code with if statements or matches or whatever. I want something like headOption for max, but I'm not seeing such a method. What's the most elegant way to get the equivalent of list.maxOption?

Tomer Shetah
  • 8,413
  • 7
  • 27
  • 35
nairbv
  • 4,045
  • 1
  • 24
  • 26

5 Answers5

15

You can convert a Try into an Option:

Try(empty.max).toOption

You can also use reduceOption (as given in scala - Min/max with Option[T] for possibly empty Seq?):

l.reduceOption(_ max _)
Community
  • 1
  • 1
Rob Napier
  • 286,113
  • 34
  • 456
  • 610
  • 4
    Although this option is very elegant, in terms of performance, an `if` is vastly cheaper than opening a `try` block and possibly generating an exception with stack trace. If you case about perf, pick one of the other options. – Leif Wickland Dec 10 '13 at 00:23
  • I like all these answers, but choosing this one for the link to even more ideas. – nairbv Dec 10 '13 at 15:21
13

Or write your own:

implicit class WithMaxOption[T: Ordering](self: Seq[T]) {
  def maxOption() = if(self.isEmpty) None else Some(self.max)
}

List(1,2,3).maxOption  // Some(3)
List[Int]().maxOption  // None
dhg
  • 52,383
  • 8
  • 123
  • 144
9

Starting in Scala 2.13, minOption/maxOption are now part of the standard library:

List(34, 11, 98, 56, 43).maxOption // Option[Int] = Some(98)
List[Int]().maxOption              // Option[Int] = None
Xavier Guihot
  • 54,987
  • 21
  • 291
  • 190
8

Here is one way to accomplish it:

Some(list).filter(_.nonEmpty).map(_.max)
thoredge
  • 12,237
  • 1
  • 40
  • 55
1

Another formulation would be

list.headOption.map(_ => list.max)
Tim
  • 26,753
  • 2
  • 16
  • 29
  • I tend to agree!The thing to remember is that the function in a map/filter method doesn't have to use the argument that is passed to it – Tim Nov 22 '17 at 07:51