代码之家  ›  专栏  ›  技术社区  ›  BAE

Scala:使用immutable不需要导入。地图

  •  2
  • BAE  · 技术社区  · 6 年前

    我在这里学习Scala https://scastie.scala-lang.org/iRJ8VOw7TySZ4KQ5qlWkdw .

    import scala.collection.mutable
    import scala.collection.mutable.ArrayBuffer
    import scala.collection.mutable.SortedSet
    // import scala.collection.immutable.Map // import not required to use immutable.Map
    
    val m = Map((1 -> "a"), (2 -> "bb"))
    
    val r = m.filter(_._1 > 1)
    
    r // Map(2 -> bb): scala.collection.immutable.Map
    
    println(r)
    

    在上述代码中, r 是一种 scala.collection.immutable.Map 即使 斯卡拉。收集不变的地图 不是进口而是 scala.collection.mutable 进口的。

    如果导入 斯卡拉。收集不变的地图 scala.collection.mutable._ ,则, R immutable.Map 如果 import scala.collection.mutable._ ,则, R mutable.Map .

    我有点困惑。有人能解释一下吗?谢谢

    5 回复  |  直到 6 年前
        1
  •  1
  •   Tim    6 年前

    第一个问题是 Map 不是从导入的 scale.collection.mutable 因为你的电脑有问题 import 陈述

    改变

    import scala.collection.mutable
    

    import scala.collection.mutable._
    

    import scala.collection.mutable.Map
    

    地图 mutable.Map .

    当您同时导入两者时 scale.collection.immutable.Map scala.collection.mutable._ 这个 immutable 地图 获胜是因为这是一个更具体的问题。所以最具体的 进口 如果你赢了,在平局的情况下,你会得到一个编译错误。

        2
  •  0
  •   Andrey Tyukin    6 年前

    这里有五个不同的问题,让我们逐一解决。


    为什么? import collection.mutable 似乎什么都不做?

    如果我们省略了代码片段中不必要的细节,我们将获得:

    import scala.collection.mutable
    val r = Map(2 -> 3)
    

    你问为什么 r 还是 scala.collection.immutable.Map .

    首先,请注意

    import scala.collection.mutable
    

    不同于

    import scala.collection.mutable._
    

    后者是通配符导入(根据需要导入可变映射),而前者只导入符号 mutable 因此,在你的代码中,只有符号 易变的 是可用的,但这并不影响 Map 无论如何。


    在哪里 斯卡拉。收集不变的地图 即使什么都没有进口,从哪里来?

    这个 Predef 始终隐式导入(除非使用编译器标志将其停用)。有一个类型别名定义

    type Map[A, +B] = collection.immutable.Map[A, B] 
    

    在里面 Predef ,还有一个直接的快捷方式可以到达 immutable.Map :

    val Map: collection.immutable.Map.type 
    

    它允许您使用 Map(...) -语法不带 new -关键词。


    为什么 import collection.immutable.Map 优先于 import collection.mutable._ ?

    这个 specification states about the precedence of imports :

    1. 本地的、继承的或由定义所在的同一编译单元中的包子句提供的定义和声明具有最高的优先级。
    2. 显式导入具有次高的优先级。
    3. 通配符导入具有次高的优先级。
    4. 由不在定义所在编译单元中的包子句提供的定义具有最低的优先级。

    因此,由于第2点和第3点,显式导入

    import scala.collection.mutable.Map
    

    优先于通配符导入

    import scala.collection.immutable._
    

    为什么? 导入集合。可变_ 制造 地图 可变的?

    现在,还有最后一件事需要澄清:为什么 mutable._ 通配符导入优先于中的定义 Predef ? 下面是一个简短的例子来说明这一点:

    import scala.collection.mutable._
    val m = Map()
    println(m.getClass)
    

    输出是(可能有点令人惊讶):

    class scala.collection.mutable.HashMap
    

    在这一点上,规范似乎有点模糊,至少我找不到它在哪里说普通通配符导入掩盖了Predef中的定义。然而 here 上面写着:

    每个编译单元按照给定的顺序隐式导入以下包:

    • 包java。朗,
    • scala软件包,以及
    • 对象scala。Predef,除非有引用scala的显式顶级导入。Predef。

    以后导入的成员按该顺序隐藏以前导入的成员。

    我认为最后一句话也涵盖了之后的进口 scala.Predef 导入,也就是通配符。这可能就是为什么 import scala.collection.mutable._ 掩盖了中的定义 Predef .


    REPL里发生了什么?

    在尝试导入时,必须记住,REPL会像在新的嵌套块中一样计算每一行。这意味着,例如,脚本

    import scala.collection.mutable._
    import scala.collection.immutable._
    Map()
    

    将导致

    error: reference to Map is ambiguous
    

    但是,如果您在REPL中逐个输入相同的行,那么就不会发生错误,您将得到一个不可变的 地图 这是因为在REPL中,上述行被解释为

    import scala.collection.mutable._
    {
      import scala.collection.immutable._
      {
        Map()
      }
    }
    

    以便最后一次导入优先。我不确定斯卡斯蒂是如何处理的,可能在那里也是一样的,所以这是你必须记住的另一个复杂问题。

        3
  •  0
  •   ixeption    6 年前

    默认情况下,Scala中的映射是不可变的。 您不能导入可变的。映射,所以它仍然是不变的。 如果像这样导入,则应该可以:

    import scala.collection.mutable.Map
    

    如果导入scala。收集不变的地图和 斯卡拉。收集易变的。 ,r是不变的。地图如果导入 斯卡拉。收集易变的。 ,r是可变的。地图

    最合格的导入语句获胜。

        4
  •  0
  •   Omprakash    6 年前

    通过 违约 Scala给了我们 不变映射 .有 两种方式 创建 可变映射 :

    **1.** Use import statement - *scala.collection.mutable._* to bring mutable map it into scope 
    **2.** Specify the full path to *scala.collection.mutable.Map*
    

    “使用导入” 导入scala。收集可变_ “,您正在导入所有可用的可变集合。” 以及可变地图 .

    如果你正在添加 斯卡拉。收集不变的地图 随着 斯卡拉。收集可变_ 你是 告诉scala编译器使用所有可变集合,但如果是Map,则使用immutable。

        5
  •  -1
  •   shanmuga    6 年前

    tl;博士 使用 import scala.collection.mutable.Map


    这是因为 m 是的实例 scala.collection.immutable.Map (默认行为)。java中的类似行为 java.lang 包已隐式导入。

    您导入了不可变的包,这不会自动纳入范围 斯卡拉。收集不变的地图 隐藏 scala.collection.mutable.Map
    为此你应该 导入scala。收集易变的。地图

    import scala.collection.mutable
    val m = Map((1 -> "a"), (2 -> "bb"))
    println(m.getClass)  // class scala.collection.immutable.Map$Map2
    
    val mutableMap = mutable.Map((1->"A"), (2->"BB"))
    println(mutableMap.getClass) // class scala.collection.mutable.HashMap
    

    或者

    import scala.collection.mutable.Map
    val m = Map((1 -> "a"), (2 -> "bb"))
    println(m.getClass)  // class scala.collection.mutable.HashMap