用参数名称替换具体值时的无限循环



我有以下两个对象(使用scala和spark):1.主要对象

object Omain {
def main(args: Array[String]) {
odbscan
}
}

2.对象odbscan

object odbscan {
val conf = new SparkConf().setAppName("Clustering").setMaster("local")
conf.set("spark.driver.maxResultSize", "3g")
val sc = new SparkContext(conf)
val param_user_minimal_rating_count = 2
/***Connexion***/
val sqlcontext = new org.apache.spark.sql.SQLContext(sc)
val sql = "SELECT id, data FROM user_profile"
val options = connectMysql.getOptionsMap(sql)
val uSQL = sqlcontext.load("jdbc", options)
val users = uSQL.rdd.map { x =>
val v = x.toString().substring(1, x.toString().size - 1).split(",")
var ap: Map[Int, Double] = Map()
if (v.size > 1)
ap = v(1).split(";").map { y => (y.split(":")(0).toInt, y.split(":")(1).toDouble) }.toMap
(v(0).toInt, ap)
}.filter(_._2.size >= param_user_minimal_rating_count) 
println(users.collect().mkString("n"))
}

当我执行这个代码时,我获得了一个无限循环,直到我改变:

过滤器(_.2.size>=param_user_minimal_rating_count)

滤波器(_.2.size>=1)

或者任何其他数值,在这种情况下代码工作,我的结果显示

认为这里发生的事情是Spark序列化函数以通过连线发送它们。因为您的函数(传递给map的函数)调用对象odbscan的访问器param_user_minimal_rating_count,所以整个对象odbscan将需要序列化并与之一起发送。反序列化然后使用该反序列化对象将导致其主体中的代码再次执行,这将导致序列化-->发送-->反序列化-->执行-->序列化-->的无限循环。。。

这里最简单的方法可能是将val更改为final val param_user_minimal_rating_count = 2,这样编译器就会内联该值。但请注意,这只是文字常量的解决方案。有关详细信息,请参见常量值定义和常量表达式。

另一个更好的解决方案是重构代码,使lambda表达式中不使用实例变量。引用在对象或类中定义的val将使整个对象序列化。所以尽量只引用本地的val(对于一个方法)。最重要的是,不要从构造函数/对象或类的主体中执行业务逻辑。

您的问题在其他地方

这两个代码段之间的唯一区别是map之外的val Eps = 5的定义,它根本不会改变代码的控制流。

请发布更多上下文,以便我们提供帮助。

最新更新