如何用Scala从无向图查找节点邻居?GraphX输出格式求助
解决GraphX collectNeighborIds输出数组地址的问题
你遇到的[J@xxx格式输出,是因为Scala中Array[VertexId]的默认toString方法会打印数组的类型标识和内存地址,而不是数组里的实际元素。要得到你期望的邻接列表格式,只需要把数组转换成逗号分隔的字符串即可,下面是具体的解决方案:
核心思路
使用Scala数组的mkString方法,将Array[VertexId]转换为逗号分隔的字符串,再拼接成你想要的(节点ID - 邻居ID1, 邻居ID2,...)格式。
修改后的代码示例
val graphx = Graph(nodes,routes) val label = sc.textFile("label.csv") val getgdata2 = label.map(line=>line.split(",")) val node11 = getgdata2.map(line=>((line(0)))).distinct // 1. 获取每个节点的邻居ID数组 val verticesWithSuccessors: VertexRDD[Array[VertexId]] = graphx.ops.collectNeighborIds(EdgeDirection.Out) // 2. 将邻居数组转换为可读的字符串格式 val verticesWithSuccessorsStr: VertexRDD[String] = verticesWithSuccessors.mapValues(neighbors => neighbors.mkString(", ")) // 3. 可选:构建新图(如果不需要后续图操作,这一步可以跳过) val successorGraph = Graph(verticesWithSuccessorsStr, routes) // 4. 收集数据并格式化为期望的输出形式 val res = successorGraph.vertices.collect() val formattedResults = res.map { case (nodeId, neighborsStr) => s"($nodeId - $neighborsStr)" } // 打印前5条结果 formattedResults.take(5).foreach(println)
简化版(跳过构建新图)
如果不需要基于邻接列表构建新的Graph对象,可以直接在收集数据后处理:
val res = verticesWithSuccessors.collect() res.take(5).foreach { case (nodeId, neighborsArr) => val neighborsStr = neighborsArr.mkString(", ") println(s"($nodeId - $neighborsStr)") }
补充说明
- 因为你构建的是无向图,使用
EdgeDirection.Out和EdgeDirection.In、EdgeDirection.Both的结果是一致的(无向图的边会被视为双向),可以根据习惯选择。 mkString方法还支持自定义分隔符,比如如果想让邻居ID之间用中文逗号分隔,改成neighbors.mkString(", ")即可。
内容的提问来源于stack exchange,提问作者Asish
相关产品推荐
相关产品推荐

