这个问题的灵感来自Extract numbers from String Array问题。
考虑我们有List
任意字母和数字字符串:
val ls = List("The", "first", "one", "is", "11", "the", "second", "is" "22")
目标是形成从原始列表中提取的数字列表:val nums: List[Int] = List(11, 22)
有两种不同的方法(AFAIK):
使用Try
构造:
val nums = ls.flatMap(s => Try(s.toInt).toOption)
此解决方案看起来简洁,但处理异常会产生巨大的开销。
使用matches
方法:
val nums = ls.filter(_.matches("\\d+")).map(_.toInt)
这里最耗时的部分是正则表达式匹配。
哪一项表现更好?
从我的角度来看,在如此简单的操作中使用异常机制就像是“使用大锤来破解坚果”。
答案 0 :(得分:2)
我强烈建议你自己测试这些东西,你可以学到很多东西!开始Scala REPL:
void test()
{
string connStr = "Provider=Microsoft.ACE.OLEDB.12.0;Data Source=|DataDirectory|\\Database1.accdb;Persist Security Info=False;";
OleDbConnection conn = new OleDbConnection(baglantiCumlesi);
conn.Open();
conn.Close();
}
好的,环境已经设置好了。这是你的第一个功能(尝试):
scala> import scala.util.Try
import scala.util.Try
< import printTime function from our repo >
scala> val list = List("The", "first", "one", "is", "11", "the", "second", "is", "22")
list: List[String] = List(The, first, one, is, 11, the, second, is, 22)
scala> var x: List[Int] = Nil
x: List[Int] = List()
第二个功能(正则表达式):
scala> def f1(l: List[String], n: Int) = {
var i = 0
while (i < n) {
x = l.flatMap(s => Try(s.toInt).toOption)
i += 1
}
}
f1: (l: List[String], n: Int)Unit
时序:
scala> def f2(l: List[String], n: Int) = {
var i = 0
while (i < n) {
x = l.filter(_.matches("\\d+")).map(_.toInt)
i += 1
}
}
f2: (l: List[String], n: Int)Unit
好吧,我们已经了解到在flatMap中处理异常是一种非常低效的方法。这部分是因为异常处理会产生错误的汇编代码,部分原因是带有选项的flatMaps会进行大量的额外分配和装箱。正则表达式快8倍!但是......快速正则表达式吗?
scala> printTime(f1(list, 100000)) // Try
time: 4.152s
scala> printTime(f2(list, 100000)) // regex
time: 565.107ms
用字符scala> def f3(l: List[String], n: Int) = {
var i = 0
while (i < n) {
x = l.filter(_.forall(_.isDigit)).map(_.toInt)
i += 1
}
}
f3: (l: List[String], n: Int)Unit
scala> printTime(f3(list, 100000)) // isDigit
time: time: 70.960ms
调用替换正则表达式给了我们另一个数量级的改进。这里的教训是不惜一切代价避免尝试/捕获处理,尽可能避免使用正则表达式,并且不要害怕编写性能比较!