for (String stock : allStocks) {
Quote quote = getQuote(...);
if (null == quoteLast) {
continue;
}
Price price = quote.getPrice();
if (null == price) {
continue;
}
}
Run Code Online (Sandbox Code Playgroud)
我不一定需要逐行翻译,但我正在寻找"Scala方式"来处理这类问题.
Mil*_*bin 28
在这种情况下你不需要继续或易碎或类似的东西:选项和理解很好地完成了这个工作,
val stocksWithPrices =
for {
stock <- allStocks
quote <- Option(getQuote(...))
price <- Option(quote.getPrice())
} yield (stock, quote, price);
Run Code Online (Sandbox Code Playgroud)
通常,您尝试在开始之前通过过滤来避免这些情况:
val goodStocks = allStocks.view.
map(stock => (stock, stock.getQuote)).filter(_._2 != null).
map { case (stock, quote) => (stock,quote, quote.getPrice) }.filter(_._3 != null)
Run Code Online (Sandbox Code Playgroud)
(此示例显示了如果需要,您将如何携带部分结果).我使用了一个视图,以便根据需要计算结果,而不是在每一步创建一堆新的集合.
实际上,你可能有引号和返回选项 - 在StackOverflow上查看如何使用它们而不是null返回值的示例.
但是,无论如何,如果那种东西不能很好地工作(例如,因为你需要保留太多的中间结果,或者你依赖于更新可变变量而你想保持评估模式简单,那么你知道发生了什么事情,你不能以不同的,可能更强大的方式设想问题,那么你可以
import scala.util.control.Breaks._
for (stock <- allStocks) {
breakable {
val quote = getQuote(...)
if (quoteLast eq null) break;
...
}
}
Run Code Online (Sandbox Code Playgroud)
该breakable构造指定了中断应该到达的位置.如果你在for循环之外放置breakable,它就像标准的Java风格中断一样.如果你把它放在里面,它的作用就像continue.
当然,如果您的条件非常少,则根本不需要继续; 只需使用if语句的else.
您的控制结构可以非常惯用地映射到以下for循环中,并且您的代码演示了Scala for循环的设计过滤类型.
for {stock <- allStocks.view
quote = getQuote(...)
if quoteLast != null
price = quote.getPrice
if null != price
}{
// whatever comes after all of the null tests
}
Run Code Online (Sandbox Code Playgroud)
顺便说一下,Scala会自动将其解析为Rex Kerr解决方案的代码
val goodStocks = allStocks.view.
map(stock => (stock, stock.getQuote)).filter(_._2 != null).
map { case (stock, quote) => (stock,quote, quote.getPrice) }.filter(_._3 != null)
Run Code Online (Sandbox Code Playgroud)
对于可能使用的所有不同类型的更复杂的流,此解决方案可能不起作用continue,但它确实解决了许多常见的流程.