Scala尾部递归java.lang.StackOverflower错误
我正在迭代查询一个名为txqueue的mysql表,该表正在不断增长 每个后续查询只考虑在上一次迭代中执行查询之后插入到txqueue表中的行 为了实现这一点,每个后续查询都会从主键(以下示例中的seqno字段)超过上一个查询中观察到的最大seqno的表中选择行 以这种方式标识的任何新插入行都将写入csv文件 其目的是使该过程无限期地运行 下面的尾部递归函数工作正常,但过了一段时间后,它会运行到java.lang.StackOverflowerError中。每个迭代查询的结果包含两到三行,结果大约每秒返回一次 有没有关于如何避免java.lang.StackOverflower错误的想法 这实际上是流媒体可以/应该实现的吗 非常感谢你的建议 下面是一段时间内有效的代码:Scala尾部递归java.lang.StackOverflower错误,scala,tail-recursion,Scala,Tail Recursion,我正在迭代查询一个名为txqueue的mysql表,该表正在不断增长 每个后续查询只考虑在上一次迭代中执行查询之后插入到txqueue表中的行 为了实现这一点,每个后续查询都会从主键(以下示例中的seqno字段)超过上一个查询中观察到的最大seqno的表中选择行 以这种方式标识的任何新插入行都将写入csv文件 其目的是使该过程无限期地运行 下面的尾部递归函数工作正常,但过了一段时间后,它会运行到java.lang.StackOverflowerError中。每个迭代查询的结果包含两到三行,结果大
object TXQImport {
val driver = "com.mysql.jdbc.Driver"
val url = "jdbc:mysql://mysqlserveraddress/mysqldb"
val username = "username"
val password = "password"
var connection:Connection = null
def txImportLoop(startID : BigDecimal) : Unit = {
try {
Class.forName(driver)
connection = DriverManager.getConnection(url, username, password)
val statement = connection.createStatement()
val newMaxID = statement.executeQuery("SELECT max(seqno) as maxid from txqueue")
val maxid = new Iterator[BigDecimal] {
def hasNext = newMaxID.next()
def next() = newMaxID.getBigDecimal(1)
}.toStream.max
val selectStatement = statement.executeQuery("SELECT seqno,someotherfield " +
" from txqueue where seqno >= " + startID + " and seqno < " + maxid)
if(startID != maxid) {
val ts = System.currentTimeMillis
val file = new java.io.File("F:\\txqueue " + ts + ".txt")
val bw = new BufferedWriter(new FileWriter(file))
// Iterate Over ResultSet
while (selectStatement.next()) {
bw.write(selectStatement.getString(1) + "," + selectStatement.getString(2))
bw.newLine()
}
bw.close()
}
connection.close()
txImportLoop(maxid)
}
catch {
case e => e.printStackTrace
}
}
def main(args: Array[String]) {
txImportLoop(0)
}
}
对象TXQImport{
val driver=“com.mysql.jdbc.driver”
val url=“jdbc:mysql://mysqlserveraddress/mysqldb"
val username=“username”
val password=“password”
变量连接:连接=null
def txImportLoop(startID:BigDecimal):单位={
试一试{
Class.forName(驱动程序)
connection=DriverManager.getConnection(url、用户名、密码)
val语句=connection.createStatement()
val newMaxID=statement.executeQuery(“从txqueue中选择max(seqno)作为maxid”)
val maxid=新迭代器[BigDecimal]{
def hasNext=newMaxID.next()
def next()=newMaxID.getBigDecimal(1)
}.toStream.max
val selectStatement=statement.executeQuery(“选择seqno,someotherfield”+
“来自txqueue,其中seqno>=”+startID+“和seqno<”+maxid)
if(startID!=maxid){
val ts=System.currentTimeMillis
val file=new java.io.file(“F:\\txqueue”+ts+“.txt”)
val bw=新缓冲写入程序(新文件写入程序(文件))
//迭代结果集
while(selectStatement.next()){
write(selectStatement.getString(1)+“,“+selectStatement.getString(2))
bw.newLine()
}
bw.close()
}
连接。关闭()
txImportLoop(maxid)
}
抓住{
案例e=>e.printStackTrace
}
}
def main(参数:数组[字符串]){
txImportLoop(0)
}
}
您的函数不是尾部递归函数(因为最后出现了catch
)。
这就是为什么最终会出现堆栈溢出
您应该始终使用
@scala.annotation.tailrec
注释要进行尾部递归的函数-如果尾部递归不可能,它将无法编译,因此您在运行时不会对此感到惊讶。您的函数不是尾部递归的(因为最后出现了catch
)。
这就是为什么最终会出现堆栈溢出
您应该始终使用@scala.annotation.tailrec
,对要进行尾部递归的函数进行注释-如果尾部递归不可能实现,则编译将失败,因此在运行时您不会对此感到惊讶