我正在映射 HBase 表,为每个 HBase 行生成一个 RDD 元素。但是,有时该行有错误数据(在解析代码中抛出 NullPointerException),在这种情况下我只想跳过它。

我的初始映射器返回 Option表示它返回 0 或 1 个元素,然后过滤 Some ,然后获取包含的值:

// myRDD is RDD[(ImmutableBytesWritable, Result)] 
val output = myRDD. 
  map( tuple => getData(tuple._2) ). 
  filter( {case Some(y) => true; case None => false} ). 
  map( _.get ). 
  // ... more RDD operations with the good data 
 
def getData(r: Result) = { 
  val key = r.getRow 
  var id = "(unk)" 
  var x = -1L 
 
  try { 
    id = Bytes.toString(key, 0, 11) 
    x = Long.MaxValue - Bytes.toLong(key, 11) 
    // ... more code that might throw exceptions 
 
    Some( ( id, ( List(x), 
          // more stuff ... 
        ) ) ) 
  } catch { 
    case e: NullPointerException => { 
      logWarning("Skipping id=" + id + ", x=" + x + "; \n" + e) 
      None 
    } 
  } 
} 

有没有更惯用的方法来做到这一点更短?我觉得这看起来很乱,都在 getData()并在 map.filter.map我正在跳舞。

也许是 flatMap可以工作(在 Seq 中生成 0 或 1 个项目),但我不希望它展平我在 map 函数中创建的元组,只需消除空。

请您参考如下方法:

另一种通常被忽视的方法是使用 collect(PartialFunction pf) ,这意味着“选择”或“收集”RDD中在部分函数中定义的特定元素。

代码如下所示:

val output = myRDD.collect{case Success(tuple) => tuple } 
 
def getData(r: Result):Try[(String, List[X])] = Try { 
        val id = Bytes.toString(key, 0, 11) 
        val x = Long.MaxValue - Bytes.toLong(key, 11) 
        (id, List(x)) 
} 


评论关闭
IT干货网

微信公众号号:IT虾米 (左侧二维码扫一扫)欢迎添加!