我试图从一个密钥的Map[String, String]
读取一个值。这个键值是可选的,因为它可能不存在所以,我想使用Option然后map
和getOrElse
如下所示来写入值,如果它在那里,或者将它设置为某个默认值,以防它不在那里。
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库中的对象。不确定这是否有所作为。
如果我理解你的问题,config.getString
会在密钥不存在时抛出异常。在这种情况下,将调用包装在Option()
中将无法捕获该异常:您应该在Try
中包装并将其转换为Option
。
Try[String]
代表一个计算,可以成功并成为一个Success(String)
,或失败,并给你一个Failure(thrownException)
。如果你熟悉Option
,这非常类似于Some
和None
的两种可能性,除了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")
您可以从这样的地图中获取值。
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")
然后,您可以使用模式匹配来提取选项中的值。或许多组合者之一map
,flatMap
,fold
等
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...))