簡體   English   中英

在Scala中處理和拋出異常

[英]Handling and throwing Exceptions in Scala

我有以下實現:

  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")
  }

基本上我正在做的是,我正在運行我的Seq並試圖用不同的格式解析DateTime。 然后我收集第一個成功的,如果不是,我將異常拋回。

我對代碼並不完全滿意。 有沒有更好的方法讓它更簡單? 我需要傳遞給調用者的異常消息。

您的代碼的一個問題是無論日期是否已經解析,它都會嘗試所有模式。 您可以使用延遲集合,如Stream來解決此問題:

 def dateTimeCSVConverter(s: String) = Stream("dd/MM/yyyy", "dd.MM.yyyy")
       .map(f => Try(DateTimeFormat.forPattern(format).parseDateTime(s))
       .dropWhile(_.isFailure)
       .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)

如果沒有匹配的模式,則返回None 如果你想在這種情況下拋出異常,你可以用getOrElse打開選項:

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

重要的是,當任何驗證成功時,它將不會更進一步,但會立即返回解析日期。

這是一種可能的解決方案,可以遍歷所有選項

  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")
      }
    })

這是一種替代解決方案,可返回第一次成功轉換(如果有)

  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")
    }
  })

我現在好像這樣甜蜜! 我更喜歡這個! 如果您想收集所有成功和所有失敗,請使用此選項。 請注意,當您需要在找到一個成功后立即退出循環時,這可能有點無效!

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