简体   繁体   English

在Scala中处理和抛出异常

[英]Handling and throwing Exceptions in Scala

I have the following implementation: 我有以下实现:

  val dateFormats = Seq("dd/MM/yyyy", "dd.MM.yyyy")
  implicit def dateTimeCSVConverter: CsvFieldReader[DateTime] = (s: String) => Try {
    val elem = dateFormats.map {
      format =>
        try {
          Some(DateTimeFormat.forPattern(format).parseDateTime(s))
        } catch {
          case _: IllegalArgumentException =>
            None
        }
    }.collectFirst {
      case e if e.isDefined => e.get
    }
    if (elem.isDefined)
      elem.get
    else
      throw new IllegalArgumentException(s"Unable to parse DateTime $s")
  }

So basically what I'm doing is that, I'm running over my Seq and trying to parse the DateTime with different formats. 基本上我正在做的是,我正在运行我的Seq并试图用不同的格式解析DateTime。 I then collect the first one that succeeds and if not I throw the Exception back. 然后我收集第一个成功的,如果不是,我将异常抛回。

I'm not completely satisfied with the code. 我对代码并不完全满意。 Is there a better way to make it simpler? 有没有更好的方法让它更简单? I need the exception message passed on to the caller. 我需要传递给调用者的异常消息。

The one problem with your code is it tries all patterns no matter if date was already parsed. 您的代码的一个问题是无论日期是否已经解析,它都会尝试所有模式。 You could use lazy collection, like Stream to solve this problem: 您可以使用延迟集合,如Stream来解决此问题:

 def dateTimeCSVConverter(s: String) = Stream("dd/MM/yyyy", "dd.MM.yyyy")
       .map(f => Try(DateTimeFormat.forPattern(format).parseDateTime(s))
       .dropWhile(_.isFailure)
       .headOption

Even better is the solution proposed by jwvh with find (you don't have to call headOption ): 更好的是jwvh使用find提出的解决方案(你不必调用headOption ):

 def dateTimeCSVConverter(s: String) = Stream("dd/MM/yyyy", "dd.MM.yyyy")
       .map(f => Try(DateTimeFormat.forPattern(format).parseDateTime(s))
       .find(_.isSuccess)

It returns None if none of patterns matched. 如果没有匹配的模式,则返回None If you want to throw exception on that case, you can uwrap option with getOrElse : 如果你想在这种情况下抛出异常,你可以用getOrElse打开选项:

 ...
 .dropWhile(_.isFailure)
 .headOption
 .getOrElse(throw new IllegalArgumentException(s"Unable to parse DateTime $s"))

The important thing is, that when any validation succeedes, it won't go further but will return parsed date right away. 重要的是,当任何验证成功时,它将不会更进一步,但会立即返回解析日期。

This is a possible solution that iterates through all the options 这是一种可能的解决方案,可以遍历所有选项

  val dateFormats = Seq("dd/MM/yyyy", "dd.MM.yyyy")
  val dates = Vector("01/01/2019", "01.01.2019", "01-01-2019")
    dates.foreach(s => {
      val d: Option[Try[DateTime]] = dateFormats
        .map(format => Try(DateTimeFormat.forPattern(format).parseDateTime(s)))
        .filter(_.isSuccess)
        .headOption
      d match {
        case Some(d) => println(d.toString)
        case _ => throw new IllegalArgumentException("foo")
      }
    })

This is an alternative solution that returns the first successful conversion, if any 这是一种替代解决方案,可返回第一次成功转换(如果有)

  val dateFormats = Seq("dd/MM/yyyy", "dd.MM.yyyy")
  val dates = Vector("01/01/2019", "01.01.2019", "01-01-2019")
  dates.foreach(s => {
    dateFormats.find(format => Try(DateTimeFormat.forPattern(format).parseDateTime(s)).isSuccess) match {
      case Some(format) => println(DateTimeFormat.forPattern(format).parseDateTime(s))
      case _ => throw new IllegalArgumentException("foo")
    }
  })

I made it sweet like this now! 我现在好像这样甜蜜! I like this a lot better! 我更喜欢这个! Use this if you want to collect all the successes and all the failures. 如果您想收集所有成功和所有失败,请使用此选项。 Note that, this might be a bit in-efficient when you need to break out of the loop as soon as you find one success! 请注意,当您需要在找到一个成功后立即退出循环时,这可能有点无效!

implicit def dateTimeCSVConverter: CsvFieldReader[DateTime] = (s: String) => Try {
    val (successes, failures) = dateFormats.map {
      case format => Try(DateTimeFormat.forPattern(format).parseDateTime(s))
    }.partition(_.isSuccess)
    if (successes.nonEmpty)
      successes.head.get
    else
      failures.head.get
  }

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM