Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/webpack/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
处理Scala映射中缺少键和空值的优雅方式_Scala - Fatal编程技术网

处理Scala映射中缺少键和空值的优雅方式

处理Scala映射中缺少键和空值的优雅方式,scala,Scala,我明白 在Scala中,应避免使用null 和Map.get将返回一个选项[B],我可以使用.getOrElse获取该值并返回默认值 e、 g 同时,我正在与一个Java库交互,其中一些值为空 e、 g。 映射(“键1”->null) 在这种情况下,getOrElse将抛出空指针 我想处理这两种情况,并得出这样的结论 def getOrElseNoNull[A,B](map:Map[A,B],key:A,default:B) = { map.get(key) match{

我明白

  • 在Scala中,应避免使用null
  • 和Map.get将返回一个选项[B],我可以使用.getOrElse获取该值并返回默认值
e、 g

同时,我正在与一个Java库交互,其中一些值为空

e、 g。 映射(“键1”->null)

在这种情况下,
getOrElse
将抛出空指针

我想处理这两种情况,并得出这样的结论

  def getOrElseNoNull[A,B](map:Map[A,B],key:A,default:B) = {
    map.get(key) match{
      case Some(x) if x != null => x
      case _ => default
    }
  }
这很难看。(它是Map[Any],我需要该键的字符串)

是否可以使用implicit来扩展地图,或使用任何其他优雅的方式?

来拯救:

implicit class NullOccludingMap[K, V](private val underlying: Map[K, V]) extends AnyVal {
  def getNonNullOrElse(key: K, default: V): V = {
    underlying.get(key) match {
      case Some(value) if value != null => value
      case _ => default
    }
  }
}
然后,您可以在范围内的任何位置使用它:

val test = Map("x" -> "Hi", "y" -> null)
test.getNonNullOrElse("z", "") // ""
test.getNonNullOrElse("y", "") // ""

实际上不需要创建新的内容,scala支持几种使用默认值实现此目的的方法:

// define a function to handle special values
Map("1" -> "2").withDefault( _ => "3").apply("4")

// default values for all unknown values
Map("1" -> "2").withDefaultValue("3").apply("4")

// handle a specific case
Map("1" -> "2").getOrElse("unknown", "3")
另一个选项是使用该选项以不太难看的方式获取空值:

None.orNull

这将获得选项值,如果没有,则返回null。

一种可能性是将值映射到
选项()

这使您能够以相同的方式处理缺少的值和空值:

val nullsEqualMissing: Map[Int, Option[String]] = withoutNulls.withDefaultValue(None)
nullsEqualMissing(1).fold{ "nullOrMissing" }{ identity }
或单独处理缺少的值:

withoutNulls.get(1).fold{ "missing" }{ _.fold{ "null" }{ identity }}

如果您处理的是一个不可变映射,最安全的做法是预先过滤掉所有空值(这会导致创建另一个映射实例,但除非您有特定的原因关心这里的性能,否则这不应该是一个问题)

任何保留null的键都将消失,因此此键上的
getOrElse
将返回
None

另一个简单的解决方案是使用Scala选项包装map.get结果

 val value = Option(map.get(key))
val nullsEqualMissing: Map[Int, Option[String]] = withoutNulls.withDefaultValue(None)
nullsEqualMissing(1).fold{ "nullOrMissing" }{ identity }
withoutNulls.get(1).fold{ "missing" }{ _.fold{ "null" }{ identity }}
val withoutNulls = map.filter{case (k,v)=> v != null}
 val value = Option(map.get(key))