我正在尝试从给定键的Map[String, String]
中读取一个值。
此键|值是可选的,因为它可能不存在
因此,我想使用Option,然后使用下面的map
和getOrElse
来写值(如果存在),或者将其设置为一些默认值(如果不存在)。
val endpoint:String = Option(config.getString("endpoint"))
.map(_.value())
.getOrElse()
上面的代码失败,显示“无法从此位置访问符号值”
config是Map[String, Object]
getString
是config上的一种方法,该方法接受密钥并返回值
public String getString(String key){
<...returns value...>
}
我可以放下Option()并这样做,但是然后我必须处理getString()抛出的异常
val endpoint:String = config.getString("endpoint")
任何想法这有什么问题,或者如何解决? 更好的编写方式?
更新:我需要提到config是导入的Java库中的一个对象。不知道这是否有所作为。
答案 0 :(得分:3)
如果我正确理解了您的问题,那么当不存在密钥时,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
。 / p>
val endpoint = Try(config.getString("endpoint")).getOrElse("your_default_value")
答案 1 :(得分: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
我怀疑config对象甚至可能具有类似的方法
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...))