【问题标题】:Elegant way handling both missing key and null values from Scala Map处理 Scala Map 中缺失键和空值的优雅方式
【发布时间】:2015-09-19 10:25:51
【问题描述】:

我明白了

  • 应避免在 Scala 中使用 null
  • Map.get 将返回一个 Option[B],我可以使用 .getOrElse 来获取值并回退到默认值

例如

map.getOrElse("key1","default")

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

例如 映射("key1"->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],我需要来自该键的字符串)

getOrElseNoNull(map,"key1","").asInstanceOf[String])

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

【问题讨论】:

    标签: scala


    【解决方案1】:

    Implicit extension classes 救援:

    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", "") // ""
    

    【讨论】:

      【解决方案2】:

      没有真正需要创建新的东西,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")
      

      另一种选择是使用 Option 以一种不那么难看的方式获取 null 值:

      None.orNull
      

      这将为您获取 Option 值或在 None 的情况下返回 null。

      【讨论】:

        【解决方案3】:

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

        val withoutNulls: Map[Int, Option[String]] = withNulls.mapValues(Option.apply)
        

        这使您可以以相同的方式处理缺失值和空值:

        val nullsEqualMissing: Map[Int, Option[String]] = withoutNulls.withDefaultValue(None)
        nullsEqualMissing(1).fold{ "nullOrMissing" }{ identity }
        

        或者单独处理缺失值:

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

        【讨论】:

          【解决方案4】:

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

          val withoutNulls = map.filter{case (k,v)=> v != null}
          

          任何持有空值的键都消失了,因此此键上的getOrElse 将返回None。 微不足道,一劳永逸。

          【讨论】:

            【解决方案5】:

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

             val value = Option(map.get(key))
            

            【讨论】:

              猜你喜欢
              • 1970-01-01
              • 2012-01-09
              • 2017-05-19
              • 1970-01-01
              • 2016-01-23
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 2011-05-25
              相关资源
              最近更新 更多