作为Java-to-Scala切换器,我经常发现自己重写了像
这样的空处理val itemOpt: Option[Item] = items.get(coords) // "items" is something like a Map
if (itemOpt.isDefined) {
val item = itemOpt.get
// do something with item, querying item fields a lot of times, for example
if (item.qty > 10) {
storeInVault(item.name, item.qty, coords)
} else {
storeInRoom(item)
}
}
我觉得它看起来很丑陋而真的看起来像是从Java重写的一段代码:
Item item = items.get(coords);
if (item != null) {
// do something with item, querying item fields a lot of times, for example
}
它在Java中看起来也很难看,但至少它只有一行。在Scala中处理这种简单案例的最佳做法是什么?我已经知道flatMap
和flatten
来处理Option[Stuff]
的集合,我知道getOrElse
来处理默认值。我梦想着像:
items.get(coords).doIfDefined(item =>
// do stuff with item
)
但我在Option
API中没有看到类似内容。
答案 0 :(得分:12)
非常受欢迎的使用模式:
val item: Option[Int] = None
val result = item map (_ + 1) getOrElse 0
所以你只需使用map
来转换价值(如果已定义)。
如果您只想使用存储在Option
内的值,那么只需使用foreach
:
item foreach { it =>
println(it)
}
如您所见,Option
也支持许多集合方法,因此您实际上不需要学习新的API。您可以将其视为具有1或0元素的集合。
答案 1 :(得分:7)
这应该可以实现您的目标:
items.get(coords).foreach{ item =>
//do stuff
}
答案 2 :(得分:5)
检查这个Tony Morris post。当我试图了解Option时,它对我非常有帮助。您的代码可能会以这样的方式重写:
for (item <- items.get(coords)) { // "items" is something like a Map
// do something with item, querying item fields a lot of times, for example
if (item.qty > 10) {
storeInVault(item.name, item.qty, coords)
} else {
storeInRoom(item)
}
}
答案 3 :(得分:3)
此外,Option可用于if
后卫的模式匹配。我个人喜欢在这种情况下使用它,并认为它更容易阅读。
因为选项上的map
仅在选项不是None
时生效,所以您可以先执行此操作,然后使用模式匹配检查您的itemOpt是否为{{ 1}}或Some
。
None