读取Parquet文件时遇Utf8转HashMap类型转换错误求助
解决Avro读取Parquet时Utf8转HashMap的类型错误
问题根源
错误org.apache.avro.util.Utf8 cannot be cast to java.util.HashMap说明你尝试强制转换的domainId字段实际值类型是Utf8,而非HashMap——要么是你对字段类型的理解有误,要么是Avro读取Map类型时返回的不是HashMap实现类。
解决方案
1. 先确认字段实际类型
在强制转换前先打印字段类型,避免逻辑错误:
val domainIdValue = i.get.get("domainId") println(domainIdValue.getClass) // 查看实际类型
如果输出是class org.apache.avro.util.Utf8,说明domainId本身是字符串字段,不是Map,直接取字符串即可:
val domainIdStr = domainIdValue.toString // 后续逻辑调整为处理字符串
2. 正确处理Avro的Map类型
如果domainId确实是Map类型,Avro读取时返回的是java.util.Map接口的实现(不一定是HashMap),应先转为通用Map类型,再处理Utf8:
// 替换原强制转换代码 val featureMap = i.get.get("domainId").asInstanceOf[java.util.Map[Utf8, Utf8]] records += featureMap .asScala .map { case (k, v) => (k.toString, v.toString) } .toMap
3. 配置Avro自动将Utf8转为String
可以全局配置Avro,让它自动把Utf8类型转为Java原生String,简化后续处理:
// 在创建AvroParquetReader之前添加这行配置 import org.apache.avro.generic.GenericData GenericData.get().setStringType(GenericData.StringType.String) // 之后读取的Map键值都会是String类型 val featureMap = i.get.get("domainId").asInstanceOf[java.util.Map[String, String]] records += featureMap.asScala.toMap
4. 优化Scala风格的循环
替换原while循环为更符合Scala习惯的Iterator方式,同时记得关闭资源:
def read(path: String): Seq[Map[String, String]] = { import org.apache.avro.generic.GenericData GenericData.get().setStringType(GenericData.StringType.String) val inputFile = HadoopInputFile.fromPath(new Path(path), configs) val reader = AvroParquetReader.builder[GenericRecord](inputFile).build() val records = Iterator.continually(Option(reader.read)) .takeWhile(_.isDefined) .flatten .map { record => val featureMap = record.get("domainId").asInstanceOf[java.util.Map[String, String]] featureMap.asScala.toMap } .toList reader.close() records }
内容的提问来源于stack exchange,提问作者sojim2
相关产品推荐
相关产品推荐

