使用带.map()和.getOrElse()的选项

问题描述 投票:2回答:2

我试图从一个密钥的Map[String, String]读取一个值。这个键值是可选的,因为它可能不存在所以,我想使用Option然后mapgetOrElse如下所示来写入值,如果它在那里,或者将它设置为某个默认值,以防它不在那里。

val endpoint:String = Option(config.getString("endpoint"))
    .map(_.value())
    .getOrElse()

上面的代码失败,“符号值无法从这个地方访问”

配置是一个Map[String, Object]

getString是一个接受密钥的配置方法,并返回该值

public String getString(String key){
    <...returns value...>
}

我可以放弃Option()并执行,但是我必须处理将由getString()抛出的异常

val endpoint:String = config.getString("endpoint")

任何想法有什么问题,或如何解决这个问题?更好的写作方式?

更新:我需要提一下,config是导入的Java库中的对象。不确定这是否有所作为。

scala
2个回答
3
投票

如果我理解你的问题,config.getString会在密钥不存在时抛出异常。在这种情况下,将调用包装在Option()中将无法捕获该异常:您应该在Try中包装并将其转换为Option

Try[String]代表一个计算,可以成功并成为一个Success(String),或失败,并给你一个Failure(thrownException)。如果你熟悉Option,这非常类似于SomeNone的两种可能性,除了Failure将包装异常以便你知道导致问题的原因。 Try(someComputation)方法将为您执行以下操作:

try {
    Success(someComputation)
} catch {
    case ex: Exception => Failure(ex)
}

要考虑的第二件事是在没有价值时你真正想要发生的事情。一个明智的想法是提供默认配置,这就是getOrElse的用途:如果不给它默认值,你就无法使用!

这是一个例子:

val endpoint = Try(config.getString("endpoint"))
    .toOption
    .getOrElse("your_default_value")

我们可以做得更好:现在我们正在使用Try来捕获异常,如果我们要立即访问该值,则无需转换为Option

val endpoint = Try(config.getString("endpoint")).getOrElse("your_default_value")

0
投票

您可以从这样的地图中获取值。

val m: Map[String, String] = Map("foo" -> "bar")
val res  = m.get("foo").getOrElse("N.A") 
val res2 = m.getOrElse("foo", "N.A") // same as above but cleaner

但也许如果你想使用模式匹配:

val o: Option[String] = m.get("foo")
val res: String = o match { 
  case Some(value) => value
  case None => "N.A"
}

最后,一种安全的方式来处理从配置读取。

val endpoint:String = config.getString("endpoint") // this can return null
val endpoint: Option[String] = Option(config.getString("endpoint")) // this will return None if endpoint is not found

我怀疑配置对象甚至可能有类似的方法

val endpoint: Option[String] = config.getStringOpt("endpoint")

然后,您可以使用模式匹配来提取选项中的值。或许多组合者之一mapflatMapfold

val endPoint = Option(config.getString("endpoint"))

def callEndPoint(endPoint: String): Future[Result] = ??? // calls endpoint

endPoint match { 
  case Some(ep) => callEndPoint(ep)
  case None     => Future.failed(new NoSuchElementException("End point not found"))
}

要么

 val foo = endPoint.map(callEndPoint).getOrElse(Future.failed(new NoSuchElement...))
© www.soinside.com 2019 - 2024. All rights reserved.